0

I want to draw a rectangle every time user clicks on the "Rectangle" button and then clicks on the JFrame based on the event x and y coordinates. I have a component class the draws the rectangle and I have another class that has JFrame mouse press listener.

My Code:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

import javax.swing.JComponent;


public class RectangleComponent extends JComponent
{

    Rectangle box;

    RectangleComponent()
    {
        box = new Rectangle(5, 10, 20, 30);
        repaint();
    }

    RectangleComponent(int x, int y)
    {
        box = new Rectangle(x, y, 20, 30);

    }

    public void paintComponent(Graphics g)
    {  
        // Recover Graphics2D
        Graphics2D g2 = (Graphics2D) g;

        // Change the color
        Color c = new Color(1.0F,0.0F,1.0F); 
        g2.setColor(c);

        // Draw a rectangle
        g2.draw(box);


    }

}


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Test2
{
    static boolean isPressed = false;

    public static void main(String[] args)
    {
        final JFrame frame = new JFrame();

        final int FRAME_WIDTH  = 400;
        final int FRAME_HEIGHT = 400;

        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        frame.setTitle("Test 2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        JPanel panel = new JPanel();
        frame.add(panel,BorderLayout.NORTH);


        final JButton btnRectangle = new JButton("Rectangle");
        panel.add(btnRectangle);

        class RectangleButtonListener implements ActionListener
        { 
            public void actionPerformed(ActionEvent event)
            {
                isPressed = true;
            }      
        }

        ActionListener rectButtonListener = new RectangleButtonListener();
        btnRectangle.addActionListener(rectButtonListener);


        class MousePressListener implements MouseListener
        {
            public void mousePressed(MouseEvent event)
            {
                int x = event.getX() ; 
                int y = event.getY() ;


                if(isPressed)
                {

                    RectangleComponent rc = new RectangleComponent(x, y); 
                    frame.add(rc);


                }


            }

            public void mouseReleased(MouseEvent event){}
            public void mouseClicked(MouseEvent event){}
            public void mouseEntered(MouseEvent event){}
            public void mouseExited(MouseEvent event){}
        }

        MousePressListener mListener = new MousePressListener();
        frame.addMouseListener(mListener);


        frame.setVisible(true);
    }

}

Now it seems to be doing what I want, but in very strange way. If I click rectangle and click on the frame I see nothing but then if I maximize the frame the rectangle appears where I click. Why is this happening and what is the fix?

Saad A
  • 1,135
  • 2
  • 21
  • 46

3 Answers3

2

To start off with, when using paintComponent() you need to Override it and call it's super method like so:

@Override
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
}

Secondly, Here is your RectangleComponent Class with some slight modifications:

public class RectangleComponent extends JComponent
{
    int x, y;

    RectangleComponent(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Color c = new Color(1.0F,0.0F,1.0F);
        g.setColor(c);

        g.drawRect(x, y, 50, 50);
    }
}

I took the x and y variables and made them member variables so we can access them in the paintComponent() method. I also removed the whole "box" idea and did all the drawing and such in the paintCompnent()

There's also some slight modifications that you should make to your Test2 Class;

Personal recommendation, I suggest switching your drawing code to the mouseReleased event. Along with calling revalidate() and repaint() on your JFrame.

public void mouseReleased(MouseEvent event)
{
    int x = event.getXOnScreen();
    int y = event.getYOnScreen();

    if(isPressed)
    {
        RectangleComponent rc = new RectangleComponent(x, y);
        frame.add(rc);
        frame.revalidate();
        frame.repaint();
    }
}

My results:

Boxes!

Community
  • 1
  • 1
Jonah
  • 1,013
  • 15
  • 25
  • Thanks for the help Jonah, but it didn't exactly worked. It doesn't seem to add more rectangles rather it just add one rectangle and upon your next click that rectangle just changes its location to where I clicked. Although you post did help and it gave me the idea I was looking for. – Saad A Mar 01 '16 at 21:10
  • Mine adds a new rectangle for each click... But happy I could be of assistance. – Jonah Mar 01 '16 at 21:12
  • If you would like help to figure it out 100% edit your questions and include what you're expecting vs what you're getting – Jonah Mar 01 '16 at 21:13
  • I am sorry it actually did work. I will accept your answers but I also figured out how to do it another way. – Saad A Mar 01 '16 at 21:16
  • That's alright. :) Glad you figured it out yourself! – Jonah Mar 01 '16 at 21:17
1

Maximizing your frame calls repaint() automatically. It would probably be easiest to call repaint() after adding the RectangleComponent to the frame.

if(isPressed)
{    
    RectangleComponent rc = new RectangleComponent(x, y); 
    frame.add(rc);
    rc.repaint();
}
djebeeb
  • 191
  • 4
-1

I figured instead of adding new component upon click, why not just update a component that already exist by adding more content to it and then repainting it.

Here how this was fixed:

import javax.swing.JComponent ;

import java.awt.event.MouseListener ;
import java.awt.event.MouseEvent ;
import java.awt.Component;
import java.awt.Graphics2D ;
import java.awt.Graphics ;
import java.awt.Shape ;
import java.util.ArrayList ;

public class ShapeComponent extends JComponent
{
      private ArrayList<Shape> shapes ;

      public ShapeComponent(ArrayList<Shape> shapes1)
      {
          shapes = shapes1;
      }

      public void paintComponent(Graphics g)
      {  

          Graphics2D g2 = (Graphics2D) g;

          for (Shape shape : shapes)
          {
              g2.draw(shape);
          }

        }
}

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Test3 
{
    static boolean isPressed = false;
    static ArrayList<Shape> shapes = new ArrayList<Shape>() ;

    public static void main(String[] args)
    {
        final JFrame frame = new JFrame();

        final int FRAME_WIDTH  = 400;
        final int FRAME_HEIGHT = 400;

        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        frame.setTitle("Test 2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        JPanel panel = new JPanel();
        frame.add(panel,BorderLayout.NORTH);


        final JButton btnRectangle = new JButton("Rectangle");
        panel.add(btnRectangle);

        class RectangleButtonListener implements ActionListener
        { 
            public void actionPerformed(ActionEvent event)
            {
                isPressed = true;
            }      
        }

        ActionListener rectButtonListener = new RectangleButtonListener();
        btnRectangle.addActionListener(rectButtonListener);

        final JComponent component = new ShapeComponent(shapes) ;
        frame.add(component);


        class MousePressListener implements MouseListener
        {
            public void mousePressed(MouseEvent event)
            {
                int x = event.getX() ; 
                int y = event.getY() ;

                System.out.println("you have press the mouse at X : " + x + " and Y : " + y);

                if(isPressed)
                {
                    Rectangle rnew = new Rectangle(x, y, 20, 30);
                    shapes.add(rnew);
                    component.repaint();

                    System.out.println("the button is pressed");
                }
                else
                {
                    System.out.println("the button is NOT pressed");
                }

            }

            public void mouseReleased(MouseEvent event){}
            public void mouseClicked(MouseEvent event){}
            public void mouseEntered(MouseEvent event){}
            public void mouseExited(MouseEvent event){}
        }

        MousePressListener mListener = new MousePressListener();
        frame.addMouseListener(mListener);



        frame.setVisible(true);
    }
}
Saad A
  • 1,135
  • 2
  • 21
  • 46