I want to program an application that lets you draw circles with a mouse click on the left side of a JFrame
, and all the points are getting \"mirrored\" to the
Let's go through your problems:
The first problem I encountered was that when I try to implement this draw-mechanic in my frame, no circles appear.
This is because you forgot to call JPanel#revalidate() and JPanel#repaint() whenever you click somewhere in the DrawCircle
class.
So, you could change your mousePressed()
method to:
@Override
public void mousePressed(MouseEvent e) {
p.add(new Point(e.getX(), e.getY()));
revalidate();
repaint();
}
Note that I also changed the e.getX()
and e.getY()
calls, because they were on the wrong places (unless you want them that way).
That will make your circles to appear, but, your DrawCircle
is really thin (I changed the height of your JFrame
to 200 for this image, otherwise it would be really tall):
The red part is your DrawCircle
panel.
To fix this you need to override its getPreferredSize()
method:
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
That will make your JPanel
to return half the size, width
and height
were passed as parameters to the constructor, and your class DrawCircle
should now look like this:
class DrawCircle extends JPanel implements MouseListener {
ArrayList<Point> p = new ArrayList<Point>();
int width = 0;
int height = 0;
public DrawCircle(int width, int height) {
this.width = width;
this.height = height;
addMouseListener(this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point point : p) {
g.fillOval(point.x, point.y, 30, 30);
}
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
p.add(new Point(e.getX(), e.getY()));
revalidate();
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
}
}
And the output would be something like this:
It works (on the whole frame) when I use container.add(new DrawCircle)
That's because by default BorderLayout
places by default the elements on the CENTER
region, and if you have nothing else in the rest of orientations (NORTH
, SOUTH
, etc) it will take the whole space.
Now let's continue with how to solve your problem:
I also made some changes to the Application
class (which in my case I renamed to CustomPaintingInHalfFrame
):
These changes were:
WIDTH
and HEIGHT
attributes.JPanel
with BorderLayout
layout, as JFrame
already has this layout by default, I simply added our DrawClass
to it.DrawCircle
panel (as you don't want a division between both (left and right) parts of your JFrame
as stated in your previous question you can simply remove it (I recommend you to leave it there while you're testing so you know where left panel ends and right panel starts.WIDTH / 2
and HEIGHT
as parameters for DrawCircle
constructor, so it can return the correct Dimension
.So, our class should now look like this:
public class CustomPaintingInHalfFrame {
int x, y;
public static final int WIDTH = 500;
public static final int HEIGHT = 200;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new CustomPaintingInHalfFrame().gui();
}
});
}
@SuppressWarnings("serial")
public void gui() {
JFrame jframe = new JFrame("Title");
DrawCircle dc = new DrawCircle(WIDTH / 2, HEIGHT);
dc.setBorder(BorderFactory.createLineBorder(Color.RED));
jframe.add(dc, BorderLayout.WEST);
jframe.setSize(WIDTH, HEIGHT);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setResizable(false);
}
}
I recommend you to rename your DrawCircle
to Circle
or something like that. As a convention, Classes names should be nouns
Rename gui()
method to createGui()
for example because, as Classes names, method names should be verbs