【问题标题】:Repaint JPanel only after window resize is finished仅在窗口调整大小完成后重新绘制 JPanel
【发布时间】:2011-10-12 05:43:43
【问题描述】:

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

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

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

您对我如何实现这一点有任何一般性的想法吗?感觉如果ComponentListener里面有onStartResize和onFinishResize回调方法会容易很多。

谢谢!

【问题讨论】:

    标签: java swing resize jpanel repaint


    【解决方案1】:

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

    附录:AnimationTest 是一个相关示例,它利用此效果在 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();
                }
            });
        }
    }
    

    【讨论】:

    • 正要给出一个五(漂亮的屏幕截图:-) - 直到我看到你的代码:在paintComponent ... tsssee中更改状态。不要,它会造成讨厌的循环!
    • 完全正确;它旨在作为做什么的一个例子。
    【解决方案2】:

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

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

    【讨论】:

    • +1 我添加了一个 example 来说明违规行为。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      最安全的方法是实现ComponentListener,它的方法componentResized(ComponentEvent e),在这个方法里面启动javax.swing.Timer,小delay 350-500ms,如果resize仍然继续只有Timer#restart()

      但是This causes the rectangles to rapidly change color.表示另一个问题,怎么可能,因为MouseListener与Resizing无关,

      【讨论】:

        【解决方案5】:

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

        如果你不使用paintAll,我不知道。

        【讨论】:

        • 错误的假设(除了 OP 把这幅画完全弄错了):没有人曾经碰过paintAll ...
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-17
        • 2021-01-10
        • 1970-01-01
        相关资源
        最近更新 更多