IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

Exécuter une tâche longue depuis un JPanel


Sujet :

AWT/Swing Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 10
    Points : 15
    Points
    15
    Par défaut Exécuter une tâche longue depuis un JPanel
    Bonsoir,

    Depuis quelques temps je me casse les dents sur un concept qui m'a l'air pourtant tout simple en Swing.
    Le principe est d'avoir un bouton dans un panel ; un clic déclenche une méthode qui va mettre à jour le contenu du panel successivement. Le problème étant jusqu'à présent, le jpanel n'actualise son affichage uniquement quand la méthode est finie.

    Voici un petit exemple de code exprimant le problème :

    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    public class panel extends JPanel {
    	private JLabel lblLabel;
     
    	/**
             * Create the panel.
             */
    	public panel() {
    		setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
     
    		lblLabel = new JLabel("label");
    		add(lblLabel);
     
    		JButton btnDone = new JButton("done");
    		btnDone.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent arg0) {
    				timeConsummingMethod();
    			}
    		});
    		add(btnDone);
     
    	}
     
    	/**
             * Do something taking long updating  JPanel
             */
    	void timeConsummingMethod() {
    		for (int j = 1; j <= 10000; j++) {
     
    			lblLabel.setText("Intération numéro " + 9);
    			validate();
     
    			System.out.println("I should update the label but i'm not");
    		}
    	}
     
    	public static void main(String[] args) {
    		JFrame frame = new JFrame("test");
    		frame.add(new panel());
    		frame.pack();
    		frame.setVisible(true);
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	}
    }
    J'ai beaucoup lu de solutions à base de Swingworker mais je ne dois pas m'y prendre de la bonne manière car en créant un Swingworker dans la méthode de l'écouteur, le résultat ne varie pas.

    Merci pour votre éclairage

  2. #2
    Membre éprouvé Avatar de fraco
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2006
    Messages : 750
    Points : 934
    Points
    934
    Par défaut
    Salut !
    en créant un Swingworker dans la méthode de l'écouteur, le résultat ne varie pas.
    Le Swingworker doit déjà exister (déclaré par exemple en même temps que les autres composants de ta frame).
    Ensuite dans l'ActionListener du bouton tu lances le Swingworker.

    Ca devrait le faire.

  3. #3
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Et il ne faut pas appeler les méthodes d'un composant dans le doInBackground comme tu le fais.

    le doInBackground se déroule hors de l'EDT, et est réservé au tâches de calcul.

    Si tu veux lors de l'exécution du doInBackground effectuer des modifications sur un composant Swing, il faut au choix passer par un SwingUtilities.invokeLater (moche comme méthode) ou utiliser le mécanisme du SwingWorker prévu à cet effet, avec la méthode publish pour publier un objet, et la méthode process (à réimplémenter) pour effectuer les modifications sur les composants. la méthode process se déroulant dans l'EDT.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 10
    Points : 15
    Points
    15
    Par défaut
    Effectivement, en créant avant le swingworker, ça fonctionne mieux. Merci pour votre aide.

    Le constructeur modifié :

    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    	public panel() {
    		setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
     
    		lblLabel = new JLabel("label");
    		add(lblLabel);
     
    		class AnswerWorker extends SwingWorker<Void, Void>
    		{
    		    protected Void doInBackground() throws Exception
    		    {
    		    	timeConsummingMethod();
    				return null;
    		    }
    		}
     
    		JButton btnDone = new JButton("done");
    		btnDone.addActionListener(new ActionListener() {
    			public void actionPerformed(ActionEvent arg0) {
    				new AnswerWorker().execute();
    			}
    		});
    		add(btnDone);
     
    	}
    J'ai conscience qu'il faudrait normalement passer par un publish pour modifier correctement le jpanel mais ça fonctionne et le projet réel utilise plein de classe imbriquées pas MVC pour un rouble, ce qui rend l'implémentation compliquée.

  5. #5
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Le problème ici est que ta timeConsumingMethod effectue des actions sur les composants depuis le dehors de l'EDT, ce qui pose régulièrement problème.

    Donc, si tu ne peux vraiment pas utiliser le publish, englobe au moins tes appels sur des composants swing dans un SwingUtilities.invokeLater

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Exécuter une tâche à heure précise ?
    Par [ZiP] dans le forum Débuter
    Réponses: 7
    Dernier message: 24/11/2008, 15h07
  2. [Access] Exécuter une requête stockée depuis ASP
    Par TheRussian dans le forum ASP
    Réponses: 4
    Dernier message: 18/06/2008, 10h17
  3. Service windows exécutant une tâche périodique
    Par Nico_stras dans le forum C#
    Réponses: 13
    Dernier message: 06/03/2008, 09h46
  4. Exécuter une tâche planifiée avec cron
    Par Olivier Regnier dans le forum Administration système
    Réponses: 6
    Dernier message: 30/03/2007, 22h13
  5. Réponses: 41
    Dernier message: 27/08/2006, 16h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo