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 :

Problème SWING et Threads


Sujet :

AWT/Swing Java

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut Problème SWING et Threads
    Bonjour à tous,

    Je suis en train de travailler sur un projet d'une application qui devra scanner un dossier et afficher en plein écran les fichiers (pdf, images et vidéos) de ce dossier.

    Voici comment mon code est organisée :
    Une classe IHM qui s'occupe de l'interface graphique
    Une classe qui s'occupe de parcours le dossier et des classes qui gère chacun des types de fichier (ces classes pour les types de fichiers sont des threads).

    J'arrive pour l'instant bien à gérer l'affichage d'un seul fichier. Le problème apparaît avec plusieurs fichiers. Pour l'instant je veux essayer d'afficher deux fichiers pdf l'un après l'autre.

    Ma classe de parcours de dossier construit un tableau des fichiers présents dans ce dossier et traite chacun des fichiers. Seulement, il faut attendre la fin du traitement du fichier précédent (par exemple, j'affiche chaque page d'un pdf pendant 5 secondes, et il faut attendre la fin de l'affichage du fichier entier pour passer au fichier suivant). Pour faire ça, le traitement d'un fichier se fait dans un thread à part et je fais appel à la méthode join() pour attendre la fin de l'affichage.

    Le problème que j'ai est que ça me bloque apparemment l'affichage des pages. Je m'explique : le traitement d'affichage se fait bien mais rien n'apparaît mais si je n'attends pas la fin du fichier, là les fichiers s'affichent bien (bien sûr il s'affiche sans attendre que le fichier précédent se soit affiché pendant la période voulu et ce n'est donc pas ce que je cherche).
    J'ai aussi essayer en synchronisant et en faisant wait() pour attendre la fin du traitement puis notify() pour avertir qu'on peut passer au fichier suivant mais ça ne marche pas non plus !

    Je vous mets ici des extraits de mes classes :
    un extrait de la classe de parcours de dossier pour traiter les .pdf :
    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
     
    private void afficherPdf(File fichierPdf)
    	{
    		GestionPdf pdfFile = new GestionPdf(fichierPdf, this);
    		affichage.rafraichir(pdfFile.getPanel());
            pdfFile.start();
            try
    		{
    			pdfFile.join();
    		} catch (InterruptedException e)
    		{
    			IHM.erreur("Problème lors de l'attente de fin de Thread PDF");
    			e.printStackTrace();
    		} finally
    		{
    			IHM.erreur("le thread pdf est fini");
    		}
    	}
    Un extrait de la classe gestionPdf qui s'occupe d'afficher correctement le composant qui gère les pdf (je me suis servi de l'API PDFRenderer), elle délègue le traitement du parcours par page à un autre thread.
    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
     
    	public void run()
    	{
    		IHM.erreur(this.getName() + " commence.");
    		TimerPdf actionPdf = new TimerPdf(this);
     
    		actionPdf.start();
    		try
    		{
    			actionPdf.join();
    		} catch (InterruptedException e)
    		{
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} finally
    		{
    			IHM.erreur(this.getName() + " s'arrete.");
    		}
    	}
     
    	public void goToPage(int numPage)
    	{
    		PDFPage page = curFile.getPage(numPage+1);
    		panel.showPage(page);
    		IHM.erreur("OK 2!");
    		panel.requestFocusInWindow();
    	}
    et enfin un extrait de la classe qui affiche le pdf page par page (5 secondes par page)
    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
     
    public void run()
    	{
    		parcourirPdf();
    	}
     
    	private synchronized void attendre(int duree)
    	{
    		try
    		{
    			this.sleep(duree);
    		} catch (InterruptedException e)
    		{
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
     
    	public void parcourirPdf()
    	{
    		for(int i=0;i<nbPages;i++)
    		{
    			gererPdf.goToPage(pageCourante);
    			pageCourante++;
    			attendre(2000);
    		}
    	}
    Voilà, rien que ça !
    J'ai l'impression que quand on fait le join() ça "endort" l'affichage qui ne se rafraichit plus.

    Si quelqu'un a une idée d'où pourrait venir le problème, merci d'avance !

  2. #2
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Ce n'est pas la solution à ton problème. Par contre, je ne comprends pas pourquoi tu utilises des Threads pour un traitement séquentiel... Autant ne pas utiliser de Thread et tu n'auras aucun problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Pour chaque fichier :
        Lire le fichier :
            pour chaque page
                lire la page
                dormir 2"

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut
    En fait j'avais essayé aussi sans Thread, mais ça me faisait le même problème.
    Donc je m'étais dit que c'était peut-être le fait que ça soit séquentiel qui faisait que ça ne s'affiche pas correctement. (j'avoue que les threads ne résolvent apparemment pas le problème)

    Mais comme tu le dis, c'est vrai que c'est plus simple de traiter séquentiellement, j'ai donc enlever les threads inutiles.
    Ce qui est bizarre, c'est que d'afficher une page il n'y a aucun problème, mais c'est l'affichage de plusieurs page à intervalle régulier qui ne marche pas.
    Concrètement je fais un Thread.sleep(5000) après l'affichage d'une page pour attendre la prochaine.
    ainsi ce code marche très bien (affichage de la première page):
    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
     
    	public void parcourirPdf()
    	{
    		gererPdf.goToPage(0);
    //		for(int i=0;i<nbPages;i++)
    //		{
    //			gererPdf.goToPage(pageCourante);
    //			pageCourante++;
    //			try
    //			{
    //				Thread.sleep(5000);
    //			} catch (InterruptedException e)
    //			{
    //				// TODO Auto-generated catch block
    //				e.printStackTrace();
    //			}
    //		}
    	}
    mais pas celui-là :
    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
     
    	public void parcourirPdf()
    	{
    //		gererPdf.goToPage(0);
    		for(int i=0;i<nbPages;i++)
    		{
    			gererPdf.goToPage(pageCourante);
    			pageCourante++;
    			try
    			{
    				Thread.sleep(5000);
    			} catch (InterruptedException e)
    			{
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}

  4. #4
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Je ne vois pas comment le problème peut se produire sans Threads sauf si l'API de lecture que tu utilises créer un Thread... M'enfin je te conseils de virer tous ces Threads cela n'a pas de sens de faire du séquentiel avec des Threads.

    EDIT: Hum, tu as édité ton message... Je regarde.

    EDIT2: Je suppose que le problème vient de ton utilisation de l'API pdf-renderer. Es-ce que tu peux me montrer ton code goToPage et ce qui est associé ? Et quand tu dis que ça ne marche pas, cela veut dire quoi ? Tu restes sur la première page, ou quoi ?

    EDIT3: pageCourante et nbPages sont-ils initialisés ? Pourquoi ne pas utiliser i plutôt que pageCourante ?

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut
    Voici le code de goToPage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    	public void goToPage(int numPage)
    	{
    		PDFPage page = curFile.getPage(numPage+1);
    		panel.showPage(page);
    		panel.requestFocusInWindow();
    	}
    panel est de type PagePanel (une classe introduite par l'api, elle hérite de JPanel). showPage permet de changer la page du fichier pdf qu'on affiche.

    Effectivement, je peux utiliser i à la place de pageCourante, j'ai supprimé pageCourante du coup.

  6. #6
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Déjà, il faut enlever l'incrémentation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PDFPage page = curFile.getPage(numPage);
    Ensuite, tu ne m'as pas répondu. C'est quoi l'erreur ou le problème ?

    Voici un code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    try {
                        // Lancé le programme qui s'occupe de la lecture 
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });
    Il permet la gestion du réaffichage dans Swing. Je ne sais pas si tu l'avais déjà mis.

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut
    Oui désolé, je m'en suis rendu compte après avoir écrit le message.
    Ce qui marche pas c'est qu'il n'affiche rien. Il passe bien par la fonction goToPage le bon nombre de fois, en attendant bien 5 secondes chaque fois mais rien ne s'affiche à l'écran.
    [edit] Pour l'incrémentation, c'est fait exprès, en fait la page 0 et la page 1 (getPage(0) et getPage(1)) affichent tous les deux la première page (et ensuite les pages 2,3,4 ... affichent bien les pages 2,3,4 ...).

  8. #8
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Je copie/colle ou cas où tu as raté mon edit précédent :

    Voici un code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    try {
                        // Lancé le programme qui s'occupe de la lecture 
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });

    Il permet la gestion du réaffichage dans Swing. Je ne sais pas si tu l'avais déjà mis.

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut
    Oui je l'avais bien mis pour lancer le programme de cette façon là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    		SwingUtilities.invokeLater(new Runnable(){
    			public void run(){
    				try
    				{
    					IHM fenetre = new IHM();
    				} catch (IOException e)
    				{
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
     
    		});
    Par contre est-ce que j'utilise invokeLater() seulement pour le lancement du programme ou est-ce que toute modification de l'affichage (par exemple lorsque je fais showPage() et requestFocusInWindow() ) doit aussi passer par cette méthode ?

  10. #10
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Oui le showPage doit être dans le run. Par contre, la création de l'IHM ne doit pas forcément y être au contraire même.

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut
    J'ai modifié la méthode goToPage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    	public void goToPage(int numPage)
    	{
    		final PDFPage page = curFile.getPage(numPage+1);
    		SwingUtilities.invokeLater(new Runnable(){
    			public void run(){
    				panel.showPage(page);
    				panel.requestFocusInWindow();
    			}
    		});
    	}
    Toujours ce problème d'affichage.
    Pour la classe IHM, c'est celle pour moi qui construit la fenêtre du programme.
    A noter, qu'avec les threads, je pouvais faire défiler les pages du pdf et elles s'affichaient bien, c'est pour ça que je pense que le problème d'affichage est lié à de la synchronisation entre thread. Il y a peut-être quelque chose qui bloque quelque part, mais je n'arrive pas à savoir quoi.

  12. #12
    Membre chevronné
    Profil pro
    Développeur Java
    Inscrit en
    Novembre 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2007
    Messages : 301
    Par défaut
    Essaie ça pour voir :

    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
    public class Main {
     
        public static void setup() throws IOException {
            JFrame frame = new JFrame("PDF Test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            PagePanel panel = new PagePanel();
            frame.add(panel);
            frame.pack();
            frame.setVisible(true);
     
            File file = new File("foo.pdf");
            RandomAccessFile raf = new RandomAccessFile(file, "r");
            FileChannel channel = raf.getChannel();
            ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
            PDFFile pdffile = new PDFFile(buf);
     
    	for(int i = 1, n = pdffile.getNumPages(); i < n; i++) {
    	    panel.showPage(pdffile.getPage(i));
    	    // Essaie avec et sans Sleep
    	}
        }
     
        public static void main(final String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    try {
                        Main.setup();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }
    }

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut
    Avec le sleep, il n'affiche rien sauf tout à la fin où il affiche la dernière page.
    Sans le sleep, il n'affiche que la dernière page (enfin surement aussi toute celle d'avant mais on n'a pas le temps de voir!).
    On dirait que c'est le sleep qui bloque l'affichage.
    Merci en tout cas de prendre le temps de réfléchir sur mon problème !

  14. #14
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 897
    Billets dans le blog
    54
    Par défaut
    Il ne faut pas faire de sleep(), wait(), join() ou quoi que ce soit (un traitement long) succeptible de bloquer l'EDT sous peine de blocage de l'affichage ! Si uniquement la derniere page s'affiche c'est tout a fait normal puisque l'EDT se charge a la fois des evenements et de l'affichage. Hors puisque tout ton traitement est effectue d'une traite dans l'EDT cela signifie qu'a aucun moment, l'interface graphique n'est redessinee et ce malgre le fait que tu appelles, eventuelllement, repaint() entre chaque chargement (repaint() indique juste a l'interface qu'elle doit se redessiner au prochain cycle d'affichage, ca ne force pas un re-affichage immediat).

    Il est par contre possible de lancer un Timer en mode repetition a intervalles reguliers, chaque appel a actionPerformed() traitant un document en particulier.

    Ou alors effectuer tout le chargement dans une Thread annexe qui mettre a jour l'interface via SwingUtilities.invokeLater(). Cette Thread separee peut alors faire son sleep() si elle en a envie sans que celan ne gene l'EDT...
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  15. #15
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 10
    Par défaut
    Merci pour tes clarifications, c'est bien ce que je pensais !
    Il suffirait donc que je place le traitement séquentiel dans une thread annexe et que les modifications d'affichage se fasse via SwingUtilities.invokeLater(), c'est bien ça ?
    Je vais essayer en tout cas et je vous tiens au courant.

    [edit] Ca marche ! Merci à tous les deux pour votre aide ! J'aurais appris quelque chose !

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

Discussions similaires

  1. Swing et thread
    Par trax44 dans le forum EDT/SwingWorker
    Réponses: 37
    Dernier message: 22/06/2006, 12h10
  2. [C#] Problème sur un Thread
    Par bisounux dans le forum Windows Forms
    Réponses: 7
    Dernier message: 27/04/2006, 20h43
  3. Problème dans un thread
    Par BNS dans le forum MFC
    Réponses: 3
    Dernier message: 23/03/2006, 14h21
  4. Problème SWING et GarbageCollector
    Par ®om dans le forum AWT/Swing
    Réponses: 10
    Dernier message: 15/02/2006, 15h19
  5. Réponses: 5
    Dernier message: 10/05/2005, 10h22

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