2010-10-29 29 views
1

Nous avons des problèmes avec les applications Java 6 qui ne s'actualisent pas correctement lors du changement de bureaux virtuels. Le problème jusqu'à présent a été reproduit sur Fedora 11 et 13 avec GNOME et Suse SLES 10 avec KDE. J'utilise le cas de test suivant pour reproduire le problème:Pourquoi un JFrame partiellement caché n'est pas correctement repeint sur Linux lors de la commutation entre les bureaux virtuels

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

Démarrer ce programme et déplacer une autre fenêtre, par exemple, une fenêtre de terminal, en partie en face de celui-ci. Attendez que l'arrière-plan de la fenêtre devienne rouge, passez à un autre bureau virtuel et attendez cinq secondes, puis revenez à votre écran d'origine. L'arrière-plan devrait maintenant être complètement vert. Au lieu de cela, ce que je reçois est une fenêtre qui n'est que partiellement mise à jour dans les parties visibles non couvertes par l'autre fenêtre, voir screen shot.

Ce problème ne se produit pas avec Java 5 et il ne se produit pas lorsque vous utilisez l'une des propriétés suivantes au démarrage:

-Dswing.handleTopLevelPaint = false

ou

-Dswing.bufferPerWindow = false

Toutefois, la désactivation de la double mise en mémoire tampon de Swing ne semble pas être une très bonne option. Est-ce un bug JDK sur Linux ou pouvons-nous faire quelque chose dans nos applications pour résoudre ce problème de repeindre? Merci d'avance, Mark.

+0

Dans un premier temps, l'extension de la classe JFrame est inutile dans votre cas, car vous ne l'utilisez pas. Pas sûr, mais cela pourrait aussi causer l'erreur Essayez juste de supprimer extends JFrame. –

+0

La suppression de "extends JFrame" ne modifie pas le comportement. – Mark

Répondre

1

Votre TimerTask doit changer l'étiquette sur le fil d'envoi d'événement, par ex.

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

Plus commodément, utilisez javax.swing.Timer, comme gestionnaire d'événements d'action exécute sur le thread de distribution des événements.

+0

Vous avez raison. J'ai foiré ceci en essayant de créer un petit cas de test reproductible. Je vais corriger cela et mettre à jour ma question. Cependant, je peux toujours reproduire le problème d'origine avec la version fixe. – Mark

+0

@Mark: Je ne vois pas de problème sur Ubuntu 10.04.1. – trashgod

+0

Étrange. Je peux reproduire le problème aussi sur Ubuntu 10.04 et 10.10 avec JDK 1.6.0_21 x86_64. – Mark

1

J'ai testé avec plusieurs jdks: sun 64bit 1.6.0_04 serveur vm, 1.6.0_21 serveur + client vm et openjdk 64bit 1.6.0_20 serveur + client vm sur mon Ubuntu x64 10.10: tous se ressemblent, la mise à jour ne fonctionne pas . Je note également qu'il varie en fonction de l'endroit où pour couvrir la fenêtre java:

  • mettre une autre fenêtre avec le coin supérieur gauche sur la fenêtre java: seule une petite ligne horizontale est pas mis à jour

  • mettre une autre fenêtre avec le coin inférieur TEF sur la fenêtre java: le rectangle à gauche de la fenêtre couvrant est pas mis à jour

  • mettre une autre fenêtre avec la gauche/droite sur la fenêtre java: arrière-plan est mis à jour comme prévu

Le comportement de mise à jour avec les côtés supérieur/inférieur droit diffère de la même manière.

Cela ne fait aucune différence si vous testez sur un écran primaire ou secondaire.

Et je peux confirmer qu'il fonctionne

  • avec vm serveur Sun 32bit jdk 1.5.0_10.

  • avec 1.6.0_21 x86 sous Windows XP en utilisant Despot en tant que gestionnaire de bureaux virtuels

Si le 1.5 java ne fonctionnerait pas, je l'aurais deviné que ce soit un problème lié pilote XX/carte graphique. Mais avec ce travail, il semble lié à la java vm.

+0

Merci pour les tests. Je suppose qu'il est maintenant temps de rapporter cela à Oracle car il semble que ce soit un bug JDK. – Mark