不重绘旧元素就无法重绘新元素
Cannot repaint new elements without repainting old ones
这是我的问题:
我制作了一个在随机位置绘制正方形的程序,它有点粗糙但是可以用。
但是问题是它不会正确重绘,我不知道在哪里但是我在代码的某个地方犯了错误。
这会导致以下情况发生:我告诉应用程序绘制 5 个正方形,它确实这样做了,但是当我告诉它绘制 6 个时,它会绘制前一个 5 + 6。
下面列出了代码,分两部分 RandomSquares 和 DrawField :
public class RandomSquares extends JPanel {
private static JFrame frame = new JFrame("Random Squares");
private static DrawField f;
private static JButton button = new JButton("Make squares");
private static final JTextField field = new JTextField(10);
private static int amount = 0;
private static void prepareFrame() {
//knoppen
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
System.out.println(amount);
amount = Integer.parseInt(field.getText());
f = new DrawField(amount);
frame.add(f, BorderLayout.CENTER);
frame.repaint();
}
});
frame.add(button, BorderLayout.NORTH);
frame.add(field, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
Listener l = new Listener();
frame.addKeyListener(l);
frame.setSize(640, 480);
}
public static class Listener implements KeyListener {
@Override
public void keyTyped(KeyEvent ke) {
//unused
}
@Override
public void keyPressed(KeyEvent ke) {
if (ke.getKeyCode() == KeyEvent.VK_R) {
System.out.println("woot!");
}
}
@Override
public void keyReleased(KeyEvent ke) {
//unused
}
}
public static void run() {
f = new DrawField(amount);
prepareFrame();
frame.setVisible(true);
}
}
public class DrawField 扩展 JComponent {
private int amount;
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public DrawField(int amount) {
this.amount = amount;
this.setSize(540, 380);
this.setBackground(Color.GREEN);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Random r = new Random();
for (int i = 0; i < amount; i++) {
g.fillRect(r.nextInt(getWidth()), r.nextInt(getHeight()),
20, 20);
}
}
}
I tell the application to draw 5 squares it does so but then when I tell it to draw 6 it will draw the previous 5 + 6.
组件未清除任何先前的绘制调用 - 请确保始终调用父绘制方法以清除任何先前的绘制。例如:
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
//custom painting here.
}
绘画方法只能用于绘画,不能设置你的属性class。
g.fillRect(r.nextInt(getWidth()), r.nextInt(getHeight()), 20, 20);
例如,如果您调整框架的大小,将在新的随机位置绘制一组全新的矩形。
当您调用 super.paintComponent() 时,旧绘图将丢失并创建新的随机矩形。
相反,您的绘画代码应该基于 class 的属性。也就是说,一旦您创建了对象,它们就应该被修复,因此重新绘制组件不会改变绘制,除非您更改属性。
请参阅 Custom Painting Approaches,了解如何使用随机数量的对象进行绘画的示例:
- 保留要绘制的对象列表
- 将对象添加到 BufferedImage,然后只绘制图像。
在您的情况下,您将为要绘制的指定数量的矩形调用 addRectangles(...)
方法。然后绘画代码将完成剩下的工作。
编辑:
回答你的基本问题。一般来说,你需要调用super.paintComponent()
来清除组件的背景,然后再进行组件的自定义绘制。
问题是您正在扩展 JComponent
,它没有任何默认绘画代码,因此背景不会被清除。两种解决方案:
- 改为扩展 JPanel(JPanel 会清除背景)。
- 将自定义绘画代码添加到您的 class 以清除背景:
类似于:
g.setColor( getBackground() );
f.fillRect(0, 0, getWidth(), getHeight());
// paint rectangle here
这是我的问题:
我制作了一个在随机位置绘制正方形的程序,它有点粗糙但是可以用。 但是问题是它不会正确重绘,我不知道在哪里但是我在代码的某个地方犯了错误。
这会导致以下情况发生:我告诉应用程序绘制 5 个正方形,它确实这样做了,但是当我告诉它绘制 6 个时,它会绘制前一个 5 + 6。
下面列出了代码,分两部分 RandomSquares 和 DrawField :
public class RandomSquares extends JPanel {
private static JFrame frame = new JFrame("Random Squares");
private static DrawField f;
private static JButton button = new JButton("Make squares");
private static final JTextField field = new JTextField(10);
private static int amount = 0;
private static void prepareFrame() {
//knoppen
button.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
System.out.println(amount);
amount = Integer.parseInt(field.getText());
f = new DrawField(amount);
frame.add(f, BorderLayout.CENTER);
frame.repaint();
}
});
frame.add(button, BorderLayout.NORTH);
frame.add(field, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
Listener l = new Listener();
frame.addKeyListener(l);
frame.setSize(640, 480);
}
public static class Listener implements KeyListener {
@Override
public void keyTyped(KeyEvent ke) {
//unused
}
@Override
public void keyPressed(KeyEvent ke) {
if (ke.getKeyCode() == KeyEvent.VK_R) {
System.out.println("woot!");
}
}
@Override
public void keyReleased(KeyEvent ke) {
//unused
}
}
public static void run() {
f = new DrawField(amount);
prepareFrame();
frame.setVisible(true);
}
}
public class DrawField 扩展 JComponent {
private int amount;
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public DrawField(int amount) {
this.amount = amount;
this.setSize(540, 380);
this.setBackground(Color.GREEN);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Random r = new Random();
for (int i = 0; i < amount; i++) {
g.fillRect(r.nextInt(getWidth()), r.nextInt(getHeight()),
20, 20);
}
}
}
I tell the application to draw 5 squares it does so but then when I tell it to draw 6 it will draw the previous 5 + 6.
组件未清除任何先前的绘制调用 - 请确保始终调用父绘制方法以清除任何先前的绘制。例如:
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
//custom painting here.
}
绘画方法只能用于绘画,不能设置你的属性class。
g.fillRect(r.nextInt(getWidth()), r.nextInt(getHeight()), 20, 20);
例如,如果您调整框架的大小,将在新的随机位置绘制一组全新的矩形。
当您调用 super.paintComponent() 时,旧绘图将丢失并创建新的随机矩形。
相反,您的绘画代码应该基于 class 的属性。也就是说,一旦您创建了对象,它们就应该被修复,因此重新绘制组件不会改变绘制,除非您更改属性。
请参阅 Custom Painting Approaches,了解如何使用随机数量的对象进行绘画的示例:
- 保留要绘制的对象列表
- 将对象添加到 BufferedImage,然后只绘制图像。
在您的情况下,您将为要绘制的指定数量的矩形调用 addRectangles(...)
方法。然后绘画代码将完成剩下的工作。
编辑:
回答你的基本问题。一般来说,你需要调用super.paintComponent()
来清除组件的背景,然后再进行组件的自定义绘制。
问题是您正在扩展 JComponent
,它没有任何默认绘画代码,因此背景不会被清除。两种解决方案:
- 改为扩展 JPanel(JPanel 会清除背景)。
- 将自定义绘画代码添加到您的 class 以清除背景:
类似于:
g.setColor( getBackground() );
f.fillRect(0, 0, getWidth(), getHeight());
// paint rectangle here