Почему частично скрытый JFrame неправильно перерисовывается в Linux при переключении между виртуальными рабочими столами - PullRequest
1 голос
/ 29 октября 2010

у нас есть проблемы с приложениями Java 6, которые не обновляются должным образом при переключении виртуальных рабочих столов. До сих пор эта проблема воспроизводилась на Fedora 11 и 13 с GNOME и Suse SLES 10 с KDE. Я использую следующий контрольный пример для воспроизведения проблемы:

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, похоже, не очень хороший вариант. Это ошибка JDK в Linux или мы можем что-то сделать в наших приложениях, чтобы исправить эту проблему перекраски?

Ответы [ 2 ]

1 голос
/ 03 ноября 2010

Я протестировал несколько jdks: сервер Sun 64bit 1.6.0_04 vm, сервер 1.6.0_21 + клиент vm и сервер openjdk 64bit 1.6.0_20 + клиент vm на моей ubuntu x64 10.10: все выглядят одинаково, обновление не работает.И я также отметил, что это отличается в зависимости от того, где закрыть окно Java:

  • помещение другого окна с верхним левым углом над окном Java: только небольшая горизонтальная линия не обновляется

  • помещение другого окна с нижним-угловым углом над окном Java: прямоугольник, оставленный от покрывающего окна, не обновляется

  • помещение другого окна слевая / правая сторона над окном Java: фон обновляется, как и ожидалось

Поведение обновления с верхними / нижними правыми сторонами отличается одинаково.

Это не имеет никакого значения, еслитестирование на основном или дополнительном экране.

И я могу подтвердить, что он работает

  • с сервером Sun 32bit JDK 1.5.0_10 VM.

  • с 1.6.0_21 x86 на WINDOWS XP с использованием dexpot в качестве менеджера виртуальных рабочих столов

Если не работает Java 1.5, я бы предположил, что это драйвер XX / видеокартысвязанная проблема.Но с этой работой, похоже, связано с Java VM.

1 голос
/ 29 октября 2010

Ваш 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, поскольку его обработчик событий действия выполняется в потоке диспетчеризации событий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...