仅在窗口调整大小完成后重新绘制 JPanel

发布于 2024-12-09 12:32:37 字数 313 浏览 0 评论 0原文

我有一个 JPanel,在上面画了四个矩形。每个矩形的颜色都是随机选择的。仅当用户单击特定矩形时,颜色才应更改。

问题是,当用户调整窗口大小时,JPanel 上的所有内容都会重复“重新绘制”。这会导致矩形快速改变颜色。

理想情况下,我需要矩形的颜色在调整大小期间保持不变。否则,我还可以使用一种解决方案进行管理,其中 JPanel 在调整大小完成后仅重新绘制一次。

您对我如何实现这一点有什么总体想法吗?我觉得如果 ComponentListener 中有 onStartResize 和 onFinishResize 回调方法会容易很多。

谢谢!

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 ideas 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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

过去的过去 2024-12-16 12:32:37

这个例子可以用来说明@kleopatra 提出的违规行为。当组件调整大小时,事件调度机制会帮助您调用 repaint()。如果您更改正在渲染的状态,例如在 paintComponent() 中,您将看到它快速循环。在下面的示例中,调整大小时底行会闪烁,而顶行保持不变。

附录:AnimationTest是一个相关示例,它利用此效果在 ComponentAdapter 中执行动画。

ResizeMe

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();
            }
        });
    }
}

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.

ResizeMe

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();
            }
        });
    }
}
简美 2024-12-16 12:32:37

您可能错误地获取了绘画逻辑(当然是猜测,没有看到任何代码:) 看起来您正在更改 PaintComponent 方法中的颜色。这违反了一般规则:绘制时不要更改组件的任何状态。

相反,请考虑具有固定颜色的矩形,直到单击它们,然后更改颜色并重新绘制。调整大小不会在任何地方发挥作用。

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.

紫竹語嫣☆ 2024-12-16 12:32:37

初始化颜色数组。单击矩形后,用新的随机颜色重新填充数组。如果数组为空,也用随机颜色填充它。将数组与矩形存储在一起。

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.

谁的年少不轻狂 2024-12-16 12:32:37

最安全的方法是实现 ComponentListener,它的方法 componentResized(ComponentEvent e),在此方法内启动 javax.swing.Timer 与小dealy 350 -500ms,如果调整大小仍然只继续Timer#restart()

但是这会导致矩形快速改变颜色。表明另一个问题,这怎么可能,因为MouseListener 与调整大小无关,

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,

故事灯 2024-12-16 12:32:37

我假设您正在使用paintAll(Graphics g)。尝试创建一个名为 redoRectangles() 的方法,该方法随机更改矩形的颜色。在初始化时调用它并作为鼠标事件。

如果您没有使用paintAll,我不知道。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文