如果不重新绘制旧元素,则无法重新绘制新元素

时间:2015-06-12 15:49:55

标签: java frame repaint

这是我的问题:

我制作了一个程序,可以在随机位置绘制正方形,它有点粗糙,但它有效。 然而问题是它不会正确重新绘制,我不知道代码中的哪个位置我犯了错误。

这会导致以下情况发生:我告诉应用程序绘制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);
}
}

公共类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);
        }

    }
}

2 个答案:

答案 0 :(得分:0)

  

我告诉应用程序绘制5个方格,但是当我告诉它绘制6时它将绘制前5 + 6。

组件未被清除任何先前的绘制调用 - 请务必始终调用父绘制方法以清除任何先前的绘制。例如:

@Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);
    //custom painting here.
}

答案 1 :(得分:0)

绘画方法只能用于绘画,而不能用于设置类的属性。

g.fillRect(r.nextInt(getWidth()), r.nextInt(getHeight()), 20, 20);

例如,如果您调整框架的大小,则会在新的随机位置绘制一组全新的矩形。

当您调用super.paintComponent()时,旧图形将丢失,并且将创建新的随机矩形。

相反,您的绘画代码应该基于类的属性。也就是说,一旦你创建了它们应该被修复的对象,所以除非你改变属性,否则重新绘制组件不会改变绘画。

有关如何使用随机数量的对象绘制的示例,请参阅Custom Painting Approaches

  1. 保持要绘制的对象列表
  2. 将对象添加到BufferedImage,然后只绘制图像。
  3. 在您的情况下,您将为要绘制的指定数量的矩形调用addRectangles(...)方法。然后绘画代码将完成剩下的工作。

    编辑:

    回答您的基本问题。通常,在进行组件的自定义绘制之前,需要调用super.paintComponent()来清除组件的背景。

    问题是您正在展开JComponent,它没有任何默认的绘画代码,因此背景不会被清除。两种解决方案:

    1. 改为扩展JPanel(JPanel确实清除了背景)。
    2. 向您的班级添加自定义绘画代码以清除背景:
    3. 类似的东西:

      g.setColor( getBackground() );
      f.fillRect(0, 0, getWidth(), getHeight());
      // paint rectangle here