问题
My application is not JFrame-oriented, it just uses one for output. I just need to be able to tell it to draw a rectangle here, clear the screen now, a few hundred times. To do this, I wrote the following code in my main, which, by my understanding, should clear the entire JFrame to a nice blue background color.
JFrame frame = new JFrame("Maze Master Premium Super-Deluxe V199.39");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int resolution = 20;
int frameWidth = horiz * resolution;
int frameHeight = vert * resolution;
frame.setMinimumSize(new Dimension(frameWidth, frameHeight));
frame.setSize(frameWidth, frameHeight);
frame.pack();
frame.setVisible(true);
frame.toFront();
Graphics g = frame.getGraphics();
g.setPaintMode();
g.setColor(Color.BLUE);
//Clear background
g.fillRect(0, 0, frameWidth, frameHeight);
frame.update(g);
But when I run this, the JFrame displays with its default light-gray background color. Do I have to have my class extend JFrame, or is it sufficient to use frame.update(g) and I'm just getting something else wrong?
回答1:
From your question, it's difficult to grasp exactly what it is you are trying to achieve. Do you simply want to change the background color of the frame or execute some custom painting???
This Graphics g = frame.getGraphics()
is never a good idea. Apart from the fact that it's possible that the getGraphics
can return null
, graphics is stateless in Java, meaning that the graphics context you use to paint with may change between paint cycles, you should never rely on or maintain a reference to it.
Apart from been the wrong approach, a JFrame
contains a number components, which are rendered on top of it, so even if this method worked, you wouldn't see any difference, because the frame is actually be covered by other components (JRootPane
and it's content pane)
Custom painting should be carried out in one of the Component
paint methods.
The following example uses a number of techniques to change and update the contents of a frame.

Firstly, it replaces the content pane with our own component. This is always required, but because I'm performing custom painting on the frame, it was the easiest. I could have simply added the PaintPane
to the frame to get a similar result.
Secondly, I use setBackground
to change the background of my component.
Thirdly, I override paintComponent
in order to perform custom painting on my component.
public class SimplePaint01 {
public static void main(String[] args) {
new SimplePaint01();
}
public SimplePaint01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.setContentPane(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private int angle = 0;
private Rectangle shape = new Rectangle(0, 0, 100, 100);
public PaintPane() {
setBackground(Color.RED);
Timer timer = new Timer(16, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
angle += 5;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = ((getWidth() - shape.width) / 2);
int y = ((getHeight() - shape.height) / 2);
shape.x = x;
shape.y = y;
g2d.setColor(Color.BLUE);
g2d.setTransform(AffineTransform.getRotateInstance(Math.toRadians(angle), x + (shape.width / 2), y + (shape.height / 2)));
g2d.fill(shape);
g2d.dispose();
}
}
}
来源:https://stackoverflow.com/questions/13849184/painting-on-jframe-without-extending