I am building a Circuit Editor using Java. I'm now at very first stage. Now I'm building a simple editor like Paint.

I've implemented a drawing-pad where you can draw straight line and continue the line until you click an right click, by a "WIRE" Button click in the frame.

I've also implemented an "OR"(Logic) Button. After clicking that button, when you click anywhere in the drawing-pad, you will get an "OR" Logic Circuit.

But now my problem is that I want to implement a SELECT Button. After clicking this button, user can select any "OR" or other "LOGIC" Gates and move that gate to any position.

Now for the coding part. I'm new to JAVA Programming. I'm an advanced programmer in C and a little bit in C++ also.
I'm using the Swing here in JAVA.

I'm taking an image every-time a line is drawn or a "OR" gate is drawn by coding some part in the paintComponent function. The code in the paintComponent function is given below.

public void paintComponent(Graphics g)
    {
        if(image == null)
        {
            image = createImage(getSize().width, getSize().height);
            graphics2D = (Graphics2D)image.getGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            clear();
        }
        g.drawImage(image, 0, 0, null);
        if(mousedragActv) g.drawLine(oldX, oldY, tmpX, tmpY);        
    }

Now all the "lines"(i.e wires) and "OR" gates are graphics class. but when i am converting them to image. I lost the class objects. So I'm not able to detect them any more. But I've to convert them to image to keep them in the drawing-pad as I'm "repaint()"-ing again and again.
As I'm not able to detect the graphics class-es any more, so I cant get them when I need them for moving to another place as they have already converted to image.

So, how can I implement this kind of SELECT. or Let me know how can I move the Graphics class object as well as keep other objects in the drawing pad too.

I've searched the Internet a lot and found Paint like Editor but the source-code is so complex that I can't get those.
Please, at least give me concept how can I proceed.

Recommended Answers

All 11 Replies

how can I move the Graphics class object

Not sure what this means. The JVM creates a Graphics class object and passes it as a parameter to the paint or paintComponent class. That is where you do your drawing using that object. You can call other methods from the paint method and pass it the Graphics object.

all the "lines"(i.e wires) and "OR" gates are graphics class

Do you mean these drawn items are in a image object?

I'm not able to detect the graphics class-es any more

Same problem. What do you mean by "graphics classes"?


Are you asking something like this:
You want to draw various shapes on the screen and then allow the to select one of the drawn shapes and to move/copy that shape to another location on the screen?

Not sure what this means. The JVM creates a Graphics class object and passes it as a parameter to the paint or paintComponent class. That is where you do your drawing using that object. You can call other methods from the paint method and pass it the Graphics object.

actually I have used a global varibale graphics2D of Graphics2D class to draw lines and other various shapes. Now I want to move those objects on the screen by Mouse Drag. That's what I want to mean.

Do you mean these drawn items are in a image object?

No, they are not image object. they are drawn using Graphics2D class but they are converted to image, as you can see the function paintComponent, that I have posted.

graphics2D = (Graphics2D)image.getGraphics();

I have done this to keep the image. As if I have not done this, then after "repaint()"-ing the previous graphics drawn will be gone and only the new one will be there. But I don't want that.

Same problem. What do you mean by "graphics classes"?

By graphics class, I want to mean Graphics2D class or Graphics class that JAVA provides.

Are you asking something like this:
You want to draw various shapes on the screen and then allow the to select one of the drawn shapes and to move/copy that shape to another location on the screen?

Yes, exactly I want this thing. User will draw lines. User will click to a button (like "OR" LOGIC GATE Button) and then click to the drawing-pad and get a Logic Gate "OR". Then user should be able to move that shapes in the drawing-pad. You get me exactly right.

Thank you for reply. I've attached the code. but for your convenience I'm posting the whole code for you. Thnks once again.

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


public class MainEditor
{
    public static void main(String[] args)
    {  
        JFrame frame = new JFrame("Circuit Editor");
        //Creates a frame with a title of "Paint it"
       
        Container content = frame.getContentPane();
        //Creates a new container
        content.setLayout(new BorderLayout());
        //sets the layout
       
        final PadDraw drawPad = new PadDraw();
        //creates a new padDraw, which is pretty much the paint program
       
        content.add(drawPad, BorderLayout.CENTER);
        //sets the padDraw in the center
       
        //for the task bar
        final JTextArea taskbar = new JTextArea();
        
        taskbar.setVisible(true);
        taskbar.setBackground(Color.lightGray);
        taskbar.setEditable(false);
        
        //adding the taskbar to the bottom-part
        content.add(taskbar,BorderLayout.SOUTH);
        
        
        JPanel panel = new JPanel();
        //creates a JPanel
        panel.setPreferredSize(new Dimension(32, 68));
        panel.setMinimumSize(new Dimension(32, 68));
        panel.setMaximumSize(new Dimension(32, 68));
        //This sets the size of the panel
       
        JButton clearButton = new JButton("CLEAR");
        clearButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                drawPad.clear();
                taskbar.setText(null);
            }
        });
       
        JButton orButton = new JButton("OR");
        orButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                drawPad.addOR();
                taskbar.setText("Click to add an OR-Gate");
            }
        });
        
        JButton wireButton = new JButton("WIRE");
        wireButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                drawPad.wire();
                taskbar.setText("Right Click to stop adding Wires.");
            }
        });
             
        panel.add(clearButton);
        panel.add(wireButton); 
        panel.add(orButton);
        //adds the buttons to the panel
       
        content.add(panel, BorderLayout.NORTH);
        //sets the panel to the upper portion
       
        frame.setSize(1000, 700);
        //sets the size of the frame
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //makes it so you can close
        frame.setResizable(false);
        //so that u can't change the dafault size
        frame.setVisible(true);
        //makes it so you can see it
    }
}


class PadDraw extends JComponent
{
    Image image;
    
    Graphics2D graphics2D;
    //this is what we'll be using to draw on
    
    //Graphics or;
    int currentX, currentY, oldX, oldY,tmpX,tmpY;
    int xpos,ypos;
    boolean mousedragActv, desn=true, orclkactv=false;
    
    MouseListener line_connct = new MouseAdapter(){
            
            //When mouse is clicked we detect if it's right-click.
            //for right click we reset the cursor but the image unchanged
            @Override
            public void mouseClicked(MouseEvent e)
            {
                if(e.getButton()== MouseEvent.BUTTON3)
                {
                    reset();
                    System.out.println("Right Button Clicked");
                }
                System.out.println(oldX+","+oldY+"--"+currentX+","+currentY+"=Click");
            }
            
            //At Moues-Press with Left-Click we only set the starting point
            @Override            
            public void mousePressed(MouseEvent e)
            {
                mousedragActv=false;
                if(desn && e.getButton()==MouseEvent.BUTTON1)
                {
                    oldX = e.getX();
                    oldY = e.getY();
                    desn=false;
                    System.out.println(oldX+","+oldY+"--"+currentX+","+currentY+"=Press");
                }
            }
            
            //At Mouse-Release we draw the line actually
            @Override
            public void mouseReleased (MouseEvent e) 
            {
                mousedragActv=false;
                currentX=e.getX();
                currentY=e.getY();
                System.out.println(oldX+","+oldY+"--"+currentX+","+currentY+"=Release");
                if(graphics2D != null && desn==false && e.getButton()==MouseEvent.BUTTON1)
                {
                    graphics2D.drawLine(oldX, oldY, currentX, currentY);
                    oldX=currentX;
                    oldY=currentY;
                    desn=false;
                }
                repaint();
            }
        };
    MouseMotionListener line_show= new MouseMotionAdapter(){
            @Override
            public void mouseDragged(MouseEvent e)
            {
                tmpX = e.getX();
                tmpY = e.getY();
                mousedragActv=true;
                repaint();
            }
            @Override
            public void mouseMoved(MouseEvent e)
            {
                mousedragActv=false;
            }
        };
    
    MouseListener add_or_ms= new MouseAdapter(){
            @Override
            public void mouseClicked(MouseEvent e)
            {
                xpos=e.getX();
                ypos=e.getY();
                System.out.println("OR CLICKED");
                graphics2D.drawArc(xpos-60, ypos-20, 120, 40, 270, 180);
                graphics2D.drawArc(xpos-30, ypos-20, 55, 40, 270, 180);
                graphics2D.drawLine(xpos+60, ypos, xpos+90, ypos);
                repaint();
            }
        };
    //Now for the constructors
    public PadDraw()
    {        
        setDoubleBuffered(false);
    }

    @Override
    public void paintComponent(Graphics g)
    {
        //System.out.println(oldX+","+oldY+"--"+currentX+","+currentY);
        if(image == null)
        {
            image = createImage(getSize().width, getSize().height);
            graphics2D = (Graphics2D)image.getGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            clear();
        }
        g.drawImage(image, 0, 0, null);
        if(mousedragActv) g.drawLine(oldX, oldY, tmpX, tmpY);        
    }
    //this is the painting bit
    //if it has nothing on it then
    //it creates an image the size of the window
    //sets the value of Graphics as the image
    //sets the rendering
    //runs the clear() method
    //then it draws the image

    public void clear()
    {
        graphics2D.setPaint(Color.white);
        graphics2D.fillRect(0, 0, getSize().width, getSize().height);
        graphics2D.setColor(Color.black);
        reset();
        defaultmouse();
        repaint();
    }
    //this is the clear
    //it sets the colors as white
    //then it fills the window with white
    //thin it sets the color back to black
    
    public void addOR()
    {
        reset();
        this.addMouseListener(add_or_ms);
        System.out.println("In the ADD_OR");
        //this.removeMouseListener(addorbyms);
    }
    
    public void wire()
    {
        defaultmouse();
        this.addMouseListener(line_connct);
        this.addMouseMotionListener(line_show);
    }
    
    public void reset()
    {
        oldX=oldY=tmpX=tmpY=currentX=currentY=0;
        desn=true;
        defaultmouse();
    }
    
    public void defaultmouse()
    {
        this.removeMouseListener(line_connct);
        this.removeMouseMotionListener(line_show);
        this.removeMouseListener(add_or_ms);
    }
}

Please ignore the comments.

probably crossposted

Actually I'm hunting for the soltuin badly. So I've asked it at many places.:'(

you have to notify on both sided that you asked question on another Forum, for another info about CrossPost seach on google

Drag and Drop is nightmare for most of PL, for Java especially, for real workaround I'd suggest put your Icon/ImageIcon to JLabel, then should be dragable from JList to JList very confortly

I think you are going to have great difficulty doing D&D on parts of a single graphic. Maybe you should consider drawing each individual draggable thing in its own JLabel (setOpaque(false)), then it's reasonably straightforward to handle clicks & drags for each JLabel.

Two approaches I see:
One- have each shape be represented by an object that knows how to draw itself and knows where it is on the screen, can listen for mouse events and change its location accordingly. There would be a list of this objects that the paint method would go through to draw on the screen.

Two- Using your current buffered image approach, have a select mode that would allow the user to draw a rectangle around a part of the buffered image and then "cut" that image out of the big image and allow it to be moved around on top of the big image. The paint method would be painting two images, the big one and the cut out one until the final position for the cut image was determined when the cut image would be drawn on and merged with the big image and the paint method would go back to only drawing the big image vs the two images.

What Norm says is true. IMHO it's a no-brainer because approach (1) deals with the objects themselves, while approach(2), while it updates the image OK, doesn't address the question of what exactly was the thing you moved.

Just for fun I knocked up this little demo of approach 1 with draggable objects (sprites) and lines connecting them. Feel free to have fun with it.

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

import javax.swing.*;

public class Demo {

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

   JFrame frame = new JFrame("drag demo");

   ArrayList<Sprite> sprites = new ArrayList<Sprite>();
   ArrayList<Line> lines = new ArrayList<Line>();

   Demo() {

      frame.setMinimumSize(new Dimension(400, 300));
      frame.setLocationRelativeTo(null);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      DrawPanel drawPanel = new DrawPanel();
      drawPanel.setLayout(null);
      frame.add(drawPanel);

      Sprite sprite = new Sprite("drag me");
      sprite.setBounds(10, 10, 50, 15);
      sprite.setForeground(Color.blue);
      drawPanel.add(sprite);
      sprites.add(sprite);

      sprite = new Sprite("and me");
      sprite.setBounds(100, 40, 50, 15);
      sprite.setForeground(Color.red);
      drawPanel.add(sprite);
      sprites.add(sprite);

      sprite = new Sprite("and me too");
      sprite.setBounds(300, 90, 65, 15);
      sprite.setForeground(Color.green);
      drawPanel.add(sprite);
      sprites.add(sprite);

      Line line = new Line(sprites.get(0), sprites.get(1));
      lines.add(line);
      line = new Line(sprites.get(1), sprites.get(2));
      lines.add(line);

      frame.setVisible(true);
   }

   class Sprite extends JLabel implements MouseListener, MouseMotionListener {
      
      // A sprite is a movable draggable object

      public Sprite(String text) {
         super(text);
         addMouseListener(this);
         addMouseMotionListener(this);
      }

      public Point getConnector() {
         // returns point where connecting line(s) should meet this sprite
         return new Point(getX() + getWidth() / 2, getY() + getHeight() / 2);
      }

      @Override
      public void paintComponent(Graphics g) {
         // can do custom drawing here...
         super.paintComponent(g);
      }

      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("\"" + getText() + "\" dragged to " + getX() + ", " + getY());
            inDrag = false;
         }
      }

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

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

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

   }

   class Line {
      
      // a Line connects two Sprites.

      Sprite sprite1, sprite2;

      public Line(Sprite s1, Sprite s2) {
         sprite1 = s1;
         sprite2 = s2;
      }

      public void paintLine(Graphics2D g2d) {
         g2d.drawLine(sprite1.getConnector().x, sprite1.getConnector().y,
               sprite2.getConnector().x, sprite2.getConnector().y);
      }

   }

   class DrawPanel extends JPanel {
      // draws lines (connecting pairs of sprites)

      @Override
      public void paintComponent(Graphics g) {
         super.paintComponent(g);
         Graphics2D g2d = (Graphics2D) g;
         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
         for (Line line : lines) {
            line.paintLine(g2d);
         }
      }
   }

}

@soham.m17: How about an update on this? What did you do in the end? How did it work?

Sorry 4 this very late reply...Got busy with xm...
I lastly use Graphics Class Object. Then just used transformation theory like x_pos=+x;
So, by that it's easy to move that object.
When mouse is dragged this addition is taken place.

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.