I want to create a java application where you can build simple logic circuits (just started learning java recently and it was just a random project idea I got off the net)

Ultimately I want the gates as icons on a pane that users can drag and drop onto a canvas but drag and drop is a bit too far ahead for now.

So I was thinking of a list next to a large white area (a panel or a canvas) and clicking on the canvas or panel should create a new instance of whatever is selected on the list. AND gate, OR gate, etc.

I made the gates by subclassing JLabel (each type of gate is a class) and setting a gif of the gate as the icon in the constructor. I also added code to handle two connections (to be used later when I connect gates on the canvas with lines) and to calculate the truth value of the connections through the gate.

The part I'm stuck on now
How can I add gates on click to a panel (or should I use a canvas) at the location of the click? Also how can I make the label movable after it's been created? If that involves drag and drop I can forget that for now, but the main problem is dynamically instantiating a class at the point of click on the panel. The class is a JLabel subclass.

Recommended Answers

All 11 Replies

In the mouse click handler just create a new AndGate() or whatever and add it to the "canvas" (an ordinary JPanel would do) at the mouse click coordinates (use absolute positioning and a null layout manager for the "canvas").
ps drag'n'drop really isn't that hard - certainly less hard than writing your own code to move things around.

how can I make the label movable after it's been created

The mouse motion listener will help you with that. It takes some playing with to get it to move smoothly but its possible.

In the mouse click handler just create a new AndGate() or whatever and add it to the "canvas" (an ordinary JPanel would do) at the mouse click coordinates (use absolute positioning and a null layout manager for the "canvas").

how do I add at an exact position though?

andgate newgate = new andgate();
angate.setbounds(evt.getX,evt.getY,100,50);
jPanel1.add(andgate);
jPanel1.revalidate();

putting that in the mouseclick event would work? I don't have my laptop right now so I'll have to try it later, but, is that it?

Also, is there any way to keep the references to these dynamically created labels?
like, if I had a Vector<cirguitgates> and added the new andgate to the vector each click event, then even if the method variable newgate gets overridden by a new gate each time, could I still access the old ones for deletion and such through the vector indices?

The mouse motion listener will help you with that. It takes some playing with to get it to move smoothly but its possible.

Ok, thanks, if i can get adding the components to a null layout, I can try this.

any way to keep the references to these dynamically created labels?

Keep them in a list, like Vector or ArrayList

Here, just for fun, is runnable demo of just how easy it is to drag a JLabel around a container and log the final position. The trick is to remember that the mouse event coordinates are relative to the object being dragged, not the container, so you have to see how much the mouse has moved, and move the JLabel by the same amount.
I deliberately left out the comments to give everyone a learning opportunity ;-)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Demo implements MouseListener, MouseMotionListener {

   public static void main(String[] args) {
      new Demo();
   }

   JLabel sprite = new JLabel("drag me");

   Demo() {
      JFrame frame = new JFrame("drag demo");
      frame.setLayout(null);
      frame.setMinimumSize(new Dimension(400, 300));
      frame.setLocationRelativeTo(null);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      sprite.setBounds(10, 10, 80, 20);
      sprite.addMouseListener(this);
      sprite.addMouseMotionListener(this);
      frame.add(sprite);

      frame.setVisible(true);
   }

   int startDragX, startDragY;
   boolean inDrag = false;

   @Override
   public void mouseEntered(MouseEvent e) {
      // not interested
   }

   @Override
   public void mouseExited(MouseEvent e) {
      // not interested
   }

   @Override
   public void mousePressed(MouseEvent e) {
      startDragX = e.getX();
      startDragY = e.getY();
   }

   @Override
   public void mouseReleased(MouseEvent e) {
      if (inDrag) {
         System.out.println("Sprite dragged to " + sprite.getX() + ", " + sprite.getY());
         inDrag = false;
      }
   }

   @Override
   public void mouseClicked(MouseEvent e) {
      // not interested
   }

   @Override
   public void mouseDragged(MouseEvent e) {
      int newX = sprite.getX() + (e.getX() - startDragX);
      int newY = sprite.getY() + (e.getY() - startDragY);
      sprite.setLocation(newX, newY);
      inDrag = true;
   }

   @Override
   public void mouseMoved(MouseEvent arg0) {
      // not interested
   }

}
commented: lots of fun +1 +9

Here, just for fun, is runnable demo of just how easy it is to drag a JLabel around a container and log the final position. The trick is to remember that the mouse event coordinates are relative to the object being dragged, not the container, so you have to see how much the mouse has moved, and move the JLabel by the same amount.
I deliberately left out the comments to give everyone a learning opportunity ;-)

Thanks! I tried the adding labels on click in the same code after I finished going through it:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
public class Test implements MouseListener, MouseMotionListener {
 
   public static void main(String[] args) {
      new Test();
   }
 
   JLabel sprite = new JLabel("drag me");
   JFrame frame = new JFrame("drag demo");
   JPanel panel = new JPanel();
 
   Test() {
      
      frame.setLayout(null);
      frame.setMinimumSize(new Dimension(500, 500));
      frame.setLocationRelativeTo(null);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      Dimension panelsize = new Dimension(400,400);
      panel.setPreferredSize(panelsize);
      panel.setBackground(Color.WHITE);
      panel.setBounds(30, 10, 400, 400);
      sprite.setBounds(10, 10, 80, 20);
      sprite.addMouseListener(this);
      sprite.addMouseMotionListener(this);
      panel.addMouseListener(this);
      panel.setLayout(null);
      frame.add(sprite);
      frame.add(panel);
 
      frame.setVisible(true);
   }
 
   int startDragX, startDragY;
   boolean inDrag = false;
 
   @Override
   public void mouseEntered(MouseEvent e) {
      // not interested
   }
 
   @Override
   public void mouseExited(MouseEvent e) {
      // not interested
   }
 
   @Override
   public void mousePressed(MouseEvent e) {
      startDragX = e.getX();
      startDragY = e.getY();
   }
 
   @Override
   public void mouseReleased(MouseEvent e) {
      if (inDrag) {
         System.out.println("Sprite dragged to " + sprite.getX() + ", " + sprite.getY());
         inDrag = false;
      }
   }
 
   @Override
   public void mouseClicked(MouseEvent e) {
       if (e.getSource()==panel){
       int clickx = e.getX();
       int clicky = e.getY();
       JLabel gate1 = new JLabel("testing");
       gate1.setBounds(clickx, clicky, 100, 50);

       panel.add(gate1);
       panel.revalidate();
       frame.validate();
       }
   }
 
   @Override
   public void mouseDragged(MouseEvent e) {
      int newX = sprite.getX() + (e.getX() - startDragX);
      int newY = sprite.getY() + (e.getY() - startDragY);
      sprite.setLocation(newX, newY);
      inDrag = true;
   }
 
   @Override
   public void mouseMoved(MouseEvent arg0) {
      // not interested
   }
 
}

now when I double click the white panel area, the label is created there, but it only shows up after I drag the "drag me" label over an area after clicking... (I thought it didnt work and just kinda waved the drag me label around in frustration and saw the clicks did create labels)

Since that seems like an odd issue and there are no exceptions, what exactly am I missing here?

Since you are NOT using a layout manager, I don't think there is a need to validate.
Try calling repaint();

That works, thanks guys, problems solved.

cool code thanks

Member Avatar for v3ga

I am in the same situation as OP(just started learning java recently and chose this as my project). All this information is very helpful. I would also like to know how to save the circuit into a file so that it can be loaded and used later

Please start your own thread for your peoblem.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.