Reputation: 1147
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?
Upvotes: 0
Views: 8509
Reputation: 1003
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:
Upvotes: 2
Reputation: 1147
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);
}
}
Upvotes: -1
Reputation: 191
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();
}
Upvotes: 1