As per comments made:
- Override
paintComponent
not paint
- Always call the super's paint method in your override. This is critical when you try to do animation (something you're sure to do next). The super's call will clean any dirty pixels.
paintComponent
should be protected, not public.
- The Swing GUI should be created on the event thread by passing a
Runnable
into the SwingUtilities.invokeLater(...)
method.
- Don't use a Graphics object obtained by calling
getGraphics()
on a Swing component (with a few exceptions). The object obtained this way will not persist or be stable, risking a disappearing image or worse, a NullPointerException. Instead Swing graphics are generally done passively by drawing within a painting method, and allowing the JVM to call this method when and where needed. This will require a paradigm shift when drawing animations.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
@SuppressWarnings("serial")
public class DrawRectPanel extends JPanel {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
private Color RECT_COLOR = Color.BLUE;
private static final int RECT_X = 80;
private static final int RECT_Y = 90;
private static final int RECT_W = 40;
private static final int RECT_H = 20;
public DrawRectPanel() {
setPreferredSize(new Dimension(PREF_W, PREF_H));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(RECT_COLOR);
g.fillRect(RECT_X, RECT_Y, RECT_W, RECT_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("DrawRectPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DrawRectPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Edit: to create 2 JFrames, change the GUI like so:
private static void createAndShowGui() {
JFrame frame = new JFrame("DrawRectPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DrawRectPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
createAndShowGui();
});
}
By setting the JFrame's location "by platform" you let the OS position it where it sees fit to do so, although I must also print a link to this related StackOverflow link: The Use of Multiple JFrames: Good or Bad Practice?