Your problem is a layout problem. Add:
System.out.println(getSize());
to your JComponent's paint method to see what happens when you resize the GUI.
This is happening because the resize is invoking the layout manager actions.
To solve this, don't use setBounds(...)
to size components but rather the layout managers. Also override your JComponent's getPreferredSize method if you want the layout managers to respect a specific size for it. Finally, don't paint with the paint
method but rather the paintComponent
method. The tutorials will explain why.
Also, if you absolutely need to position something using absolute positioning, then the container must use a null layout:
// The panel to which my SimpleCanvas objects are added
paintArea = new JPanel(null);
Edit
If I were doing something like your program above, I'm not sure that I'd add new components to a JPanel but rather would simply have the drawing JPanel hold a list of Shapes and then have the shapes drawn in its paintComponent method using a for loop. For example:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class SimpleFrame2 extends JPanel {
private static final Color ELLIPSE_COLOR = Color.LIGHT_GRAY;
private static final Color ELLIPSE_FILL_COLOR = Color.blue;
private static final int PREF_W = 600;
private static final int PREF_H = 500;
public static final int ELLIPSE_WIDTH = 100;
public static final int ELLIPSE_HEIGHT = 50;
private static final Stroke ELLIPSE_STROKE = new BasicStroke(2f);
private List<Shape> shapes = new ArrayList<Shape>();
public SimpleFrame2() {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent mEvt) {
double x = mEvt.getX() - ELLIPSE_WIDTH / 2;
double y = mEvt.getY() - ELLIPSE_HEIGHT / 2;
double w = ELLIPSE_WIDTH;
double h = ELLIPSE_HEIGHT;
shapes.add(new Ellipse2D.Double(x, y, w, h));
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// to draw smooth edges
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(ELLIPSE_STROKE);
for (Shape shape : shapes) {
g2.setColor(ELLIPSE_FILL_COLOR);
g2.fill(shape);
g2.setColor(ELLIPSE_COLOR);
g2.draw(shape);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SimpleFrame2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleFrame2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Edit 2
with dragging of shapes
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class SimpleFrame3 extends JPanel {
private static final Color ELLIPSE_COLOR = Color.LIGHT_GRAY;
private static final Color ELLIPSE_FILL_COLOR = Color.blue;
private static final int PREF_W = 600;
private static final int PREF_H = 500;
public static final int ELLIPSE_WIDTH = 100;
public static final int ELLIPSE_HEIGHT = 50;
private static final Stroke ELLIPSE_STROKE = new BasicStroke(2f);
private List<RectangularShape> rects = new ArrayList<RectangularShape>();
public SimpleFrame3() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// to draw smooth edges
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(ELLIPSE_STROKE);
for (RectangularShape rect : rects) {
g2.setColor(ELLIPSE_FILL_COLOR);
g2.fill(rect);
g2.setColor(ELLIPSE_COLOR);
g2.draw(rect);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
class MyMouseAdapter extends MouseAdapter {
private RectangularShape selectedRect = null;
private Point deltaPt = null;
@Override
public void mousePressed(MouseEvent mEvt) {
if (mEvt.getButton() != MouseEvent.BUTTON1) {
return;
}
if (rects.size() > 0) {
for (int i = rects.size() - 1; i >= 0; i--) {
if (rects.get(i).contains(mEvt.getPoint())) {
selectedRect = rects.get(i);
rects.remove(selectedRect);
rects.add(rects.size(), selectedRect);
deltaPt = new Point(mEvt.getX() - selectedRect.getBounds().x,
mEvt.getY() - selectedRect.getBounds().y);
repaint();
return;
}
}
}
double x = mEvt.getX() - ELLIPSE_WIDTH / 2;
double y = mEvt.getY() - ELLIPSE_HEIGHT / 2;
double w = ELLIPSE_WIDTH;
double h = ELLIPSE_HEIGHT;
Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
rects.add(ellipse);
selectedRect = ellipse;
deltaPt = new Point((int)(mEvt.getX() - x), (int)(mEvt.getY() - y));
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
if (selectedRect != null) {
Rectangle bounds = selectedRect.getBounds();
bounds.setLocation(e.getX() - deltaPt.x, e.getY() - deltaPt.y);
selectedRect.setFrame(bounds.x, bounds.y, bounds.width, bounds.height);
repaint();
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (selectedRect != null) {
repaint();
selectedRect = null;
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SimpleFrame3");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleFrame3());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}