Repaint JPanel only after window resize is finished
I have a JPanel on which I've painted four rectangles. The color for each of these rectangles is selected at random. The colors should change only when the user clicks on a particular rectangle.
The problem is, while a user is resizing the window, everything on the JPanel is 'repainted' repeatedly. This causes the rectangles to rapidly change color.
Ideally, I would need the colors of the rectangles to stay the same during a resize. Otherwise, I could also manage with a solution where the JPanel is repainted only once after a resize has been completed.
Do you have any general i开发者_运维问答deas on how I could implement this? I feel like it would have been a lot easier if there was a onStartResize and onFinishResize callback method in ComponentListener.
Thanks!
This example may serve to illustrate the violation adduced by @kleopatra. As a component is resized, the event dispatch mechanism helpfully invokes repaint()
for you. If you change the state of what you're rendering, say in paintComponent()
, you'll see it cycle rapidly. In the example below, the bottom row flickers as you resize, while the top row remains unchanged.
Addendum: AnimationTest
is a related example that takes advantage of this effect to perform animation in a ComponentAdapter
.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/** @https://stackoverflow.com/questions/7735774 */
public class ResizeMe extends JPanel {
private static final int N = 4;
private static final int SIZE = 100;
private static final Random rnd = new Random();
private final List<JLabel> list = new ArrayList<JLabel>();
private boolean randomize;
public ResizeMe(boolean randomize) {
this.randomize = randomize;
this.setLayout(new GridLayout(1, 0));
for (int i = 0; i < N; i++) {
JLabel label = new JLabel();
label.setPreferredSize(new Dimension(SIZE, SIZE));
label.setOpaque(true);
list.add(label);
this.add(label);
}
initColors();
this.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
System.out.println(e);
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (randomize) {
initColors();
}
}
private void initColors() {
for (JLabel label : list) {
label.setBackground(new Color(rnd.nextInt()));
}
}
private static void display() {
JFrame f = new JFrame("ResizeMe");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(0, 1));
f.add(new ResizeMe(false), BorderLayout.NORTH);
f.add(new ResizeMe(true), BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
display();
}
});
}
}
you are probably getting the painting logic incorrectly (guessing of course, without seeing any code :) Looks like you're changing the color in the paintComponent method. Which violates the general rule: Dont change any state of the component while painting.
Instead think of the rectangle having fixed colors until they are clicked, then change the color and repaint. Resizing doesn't come into the play anywhere.
Initialize an array of Colors. On click on the rect refill the array with new random colors. If the array is empty also fill it with random Colors. Store the array together with the Rectangles.
that right the safiest way is implemnts ComponentListener, its method componentResized(ComponentEvent e), inside this method start javax.swing.Timer with small dealy 350-500ms, if resize still continue only Timer#restart()
,
but This causes the rectangles to rapidly change color.
indicate another problem, how is that possible, because MouseListener
has nothing to do with Resizing,
I assume you're using paintAll(Graphics g)
. Try creating a method called redoRectangles()
, which randomly changes the colors of the rectangles. Call it at initialization and as a mouse event.
If you're not using paintAll
, I have no idea.
精彩评论