Here is my problem :
I have made a program that draws squares at random locations, its a tad crude but it works. However the problem is that it will not repaint properly, I don't know where but somewhere in the code I made a mistake.
This causes the following to happen : 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.
The code is listed below in two parts RandomSquares and 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 extends 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);
}
}
}
Painting methods should only be used for painting, not setting properties of your class.
For example if you resize the frame a whole new set of rectangles will be painted at new random locations.
When you invoke super.paintComponent(), the old drawing will be lost and new random rectangle will be created.
Instead your painting code should be based on properties of the class. That is once you create the objects they should be fixed so a repaint of the component does not change the painting, unless you change the properties.
See Custom Painting Approaches for examples of how to painting with a random number of objects by:
In your case you would invoke the
addRectangles(...)
method for the specified number of rectangle you want to paint. Then the painting code will do the rest.Edit:
To answer your basic question. In general you need to invoke
super.paintComponent()
to clear the background of a component before doing the custom painting of the component.The problem is that you are extending
JComponent
, which doesn't not have any default painting code, so the background doesn't get cleared. Two solutions:Something like: