1

我们遇到了 Java 6 应用程序在切换虚拟桌面时无法正确刷新的问题。到目前为止,该问题已在带有 GNOME 的 Fedora 11 和 13 以及带有 KDE 的 Suse SLES 10 上重现。我使用以下测试用例来重现问题:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;

public class RepaintTest {
    private JLabel label;

    private void createAndShowGUI() {
        final JFrame frame = new JFrame("RepaintTest");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        label = new JLabel("Repaint Test");
        label.setOpaque(true);
        frame.getContentPane().add(label);
        frame.pack();
        frame.setSize(200, 100);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                final RepaintTest repaintTest = new RepaintTest();
                repaintTest.createAndShowGUI();
                new Timer(5000, new ActionListener() {
                    boolean flip;
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        repaintTest.label.setBackground(flip ? Color.GREEN : Color.RED);
                        flip = !flip;
                    }
                }).start();
            }
        });
    }
}

启动此程序并移动另一个窗口,例如终端窗口,部分位于其前面。等待窗口背景变为红色,切换到另一个虚拟桌面并等待五秒钟,然后切换回原来的屏幕。现在背景应该是完全绿色的。相反,我得到的是一个仅在其他窗口未覆盖的可见部分中部分更新的窗口。

Java 5 不会出现此问题,并且在启动时使用以下属性之一时不会出现此问题:

-Dswing.handleTopLevelPaint=false 

或者

-Dswing.bufferPerWindow=false

但是,关闭 Swing 的双缓冲似乎不是一个很好的选择。这是 Linux 上的一个 JDK 错误,还是我们可以在我们的应用程序中做任何事情来解决这个重绘问题?

4

2 回答 2

1

TimerTask需要更改事件调度线程上的标签,例如

new Timer().schedule(new TimerTask() {
    boolean flip;
    @Override
    public void run() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                repaintTest.label.setBackground(flip ? Color.GREEN : Color.RED);
                flip = !flip;
            }
        });
    }
}, 5000, 5000);

更方便的是,使用javax.swing.Timer, 因为它的动作事件处理程序在事件调度线程上执行。

于 2010-10-29T17:29:39.150 回答
1

我在我的 ubuntu x64 10.10 上测试了多个 jdks:sun 64bit 1.6.0_04 server vm、1.6.0_21 server+client vm 和 openjdk 64bit 1.6.0_20 server + client vm:看起来都一样,更新不起作用。而且我还注意到它会根据覆盖 java 窗口的位置而有所不同:

  • 将另一个左上角的窗口放在java窗口上:只有一条小的水平线没有更新

  • 将另一个窗口的左下角放在 java 窗口上:覆盖窗口左侧的矩形未更新

  • 将左侧/右侧的另一个窗口放在 java 窗口上:背景按预期更新

具有上/右下侧的更新行为以相同的方式不同。

如果在主屏幕或辅助屏幕上进行测试,则没有任何区别。

我可以确认它正在工作

  • 使用 sun 32 位 jdk 1.5.0_10 服务器虚拟机。

  • 使用 1.6.0_21 x86 ON WINDOWS XP 使用 dexpot 作为虚拟桌面管理器

如果 1.5 java 不能工作,我猜它是 XX/显卡驱动相关的问题。但是有了这个工作,它似乎与java vm有关。

于 2010-11-03T10:18:08.410 回答