Bonjour,

Je voudrais des expliquations sur l'EDT et la manière de faire des menus non bloquant. J'ai lu le très interressant tutoriel Threads et performance avec Swing de Romain Guy, mais je le trouve trop succinct.

J'ai un cas concret que je n'arrive pas a comprendre :

Voila, j'ai un AbstractAction qui me permet de gérer l'affichage d'une fenêtre permettant de paramétrer mon appli. Cette action est associé a un JMenuItem et un JButton d'une JToolBar. EcranPreferences est un JDialog modal, le paramètre ecran du constructeur est la fenêtre principale de l'appli.

Voici le code de actionPerformed :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
public void actionPerformed(ActionEvent e) {
	System.out.println("EDT: "+SwingUtilities.isEventDispatchThread());
        EcranPreferences ecranPref = new EcranPreferences(ecran);
	ecranPref.setLocationRelativeTo(null);
	ecranPref.setVisible(true);
}
D'après ce que j'ai compris du tutoriel, le code qui gère de l'affichage graphique (a l'exception d'un repaint ou revalidate qui sont thread-safe) doit s'exécuté dans l'EDT. Or ici SwingUtilities.isEventDispatchThread() indique true, donc ce code est éxécuté dans l'EDT. Pourtant le bouton ou l'item du menu est bloqué (et l'appli). Pourquoi ?

Je dois éxécuter le code dans un Thread pour que le comportement ne soit plus bloquant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
public void actionPerformed(ActionEvent e) {
	final Thread th = new Thread(new Runnable() {
		public void run() {
	        	System.out.println("EDT: "+SwingUtilities.isEventDispatchThread());
		        EcranPreferences ecranPref = new EcranPreferences(ecran);
			ecranPref.setLocationRelativeTo(null);
			ecranPref.setVisible(true);
	        }
	});
	th.start();
}
Mais alors SwingUtilities.isEventDispatchThread() indique false, donc le code n'est plus exécuté dans l'EDT mais dans le Thread que je viens de créer. Pourtant cela fonctionne tel que je le souhaiterais. Pourquoi ?

Si j'ajoute un invokeLater dans le Thread pour que le code s'éxécute dans l'EDT, cela est de nouveau bloquant. Pourtant, SwingUtilities.isEventDispatchThread() indique true, donc ce code est éxécuté dans l'EDT.

Pourquoi ?

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void actionPerformed(ActionEvent e) {
	final Thread th = new Thread(new Runnable() {
		public void run() {
	            	EventQueue.invokeLater(new Runnable() {
	         		public void run() {
	            			System.out.println("EDT: "+SwingUtilities.isEventDispatchThread());
	    		        	EcranPreferences ecranPref = new EcranPreferences(ecran);
	    				ecranPref.setLocationRelativeTo(null);
	    				ecranPref.setVisible(true);
            			}
            		});
            	}
        });
	th.start();
}
Enfin, qu'est-ce que l'on doit mettre dans l'EDT, qu'est que l'on ne doit pas mettre ? Comment savoir que telle méthode doit être exécutée dans l'EDT et que tel autre ne doit pas l'être ? Tout cela semble clair en théorie, mais en pratique c'est assez déconcertant !

Un peu d'aide et de transfert d'expérience ne serait pas de refus