我可以批量处理一些Swing组件更新,以便重新绘制所有内容吗?

时间:2010-01-01 06:10:37

标签: java swing

我的JToolBar中有一堆按钮,我根据应用程序的状态将其中一些设置为禁用或启用。我发现当我一次更新一些按钮时,它们并非同时重新绘制。我想确保当我设置一些禁用/启用的按钮时,它们都会同时改变状态。

下面是一个小测试,演示了这个问题。 (它需要当前目录中的文件a.png用作按钮图标。)运行时,会显示一个带有10个按钮的工具栏。在终端按Enter键将切换所有按钮的禁用状态。至少在我的机器上,每次执行此操作时,按钮都会以看似随机的顺序重新绘制,而不是一次性完成。

似乎双缓冲可以解决问题,虽然我尝试的第一件事(在JToolBar上设置双缓冲)似乎没有影响任何东西。

谢谢,

卡梅伦

import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

public class Test {
    public static void main(String[] args) throws IOException {
        final JButton[] bs = new JButton[10];
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new JFrame("test");
                JToolBar t = new JToolBar();
                f.getContentPane().add(t);
                for (int i = 0; i < bs.length; i++) {
                    bs[i] = new JButton(new ImageIcon("a.png"));
                    t.add(bs[i]);
                }
                f.pack();
                f.setVisible(true);
            }
        });
        BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
        for (;;) {
            r.readLine();
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    for (JButton b : bs) {
                        b.setEnabled(!b.isEnabled());
                    }
                }
            });
        }
    }
}

3 个答案:

答案 0 :(得分:2)

只要在一个事件线程运行中发生启用状态更改,就会发生这种情况,以便在无效状态之间无法进行任何操作。所以我想这只是一个绘画问题?它看起来很糟糕?

更改行为的一种可能方法是为容器添加重绘调用(例如工具栏),以便一次重新绘制更大的区域,而不是单独重新绘制每个按钮。

答案 1 :(得分:1)

在XP上使用JDK6可以正常使用。

我发现您的代码没有任何问题。我一次启用/禁用了多个组件而没有问题。

问题是因为您接受来自终端的输入?尝试在框架上添加一个单独的按钮,这样点击它就会导致按钮的状态发生变化。

答案 2 :(得分:0)

@camickr我在Windows 7上使用JDK6。我使用EventQueue.invokeLater()启动了更改,因为在我的应用程序中,导致工具栏按钮需要更新状态的原因发生在另一个线程中,所以我使用EventQueue。 invokeLater()那里。我尝试从EDT做所有事情(即,从其中一个按钮上的ActionListener执行setEnabled()调用)但我仍然有同样奇怪的重新绘制。

@iny对,它看起来很糟糕。我确实认为,因为所有的状态变化都发生在一个EventQueue Runnable中,所有的绘画都会在它结束后立刻发生,但我猜不是。你在JToolBar上调用repaint()的建议确实合并了按钮的所有绘画,谢谢! (一旦我的未注册帐户(我似乎无法回复)和我最近注册的帐户合并,我将接受您的回答。)