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

PyQt Python Discussion :

QProgressDialog indéterminé avec rafraichissement de l'affichage [QtGui]


Sujet :

PyQt Python

  1. #1
    Membre actif
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Octobre 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 330
    Points : 207
    Points
    207
    Par défaut QProgressDialog indéterminé avec rafraichissement de l'affichage
    Bonjour à tous,

    J'ai dans mon appli une procédure de calcul qui peut être relativement longue mais dont j'ignore la durée totale. Je cherche depuis un bon moment comment afficher un QProgressDialog qui défile en continu
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            self.progressDialog.setRange(0, 0)
    et qui m'affiche également et régulièrement la durée écoulée depuis le lancement de la procédure. Je pense qu'il faut utiliser un QTimer et peut être gérer un thread mais je suis un peu sec sur ce coup pour l'instant.
    Merci d'avance pour vos pistes et suggestions.
    @+

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Voilà le principe que j'utiliserais dans ce cas:

    - le programme principal (la fenêtre de l'application) lance:
    => le calcul dans un QThread (pour éviter de geler le graphique).
    => une fenêtre de progression QProgressDialog avec une chenille circulante
    => un QTimer qui enverra un signal "timeout" tous les, par exemple, 0.5s.

    - à chaque fois que le QTimer envoie son signal à la fenêtre principale, celle-ci signale le temps passé à la fenêtre de progression avec la méthode .setLabelText(tempspassé)

    - quand le calcul est terminé, le QThread envoie un signal de fin à la fenêtre principale qui arrête le QTimer avec .stop() et la fenêtre de progression avec .reset()

    L'avantage du QThread sur un threading.Thread() est la capacité de lancer des messages au graphique, car les threads ne peuvent pas, en général, toucher au graphique directement (les bibliothèques graphiques ne sont pas "thread-safe"). On pourrait aussi utiliser une classe avec un héritage multiple threading.Thread + QObjet mais ça ne simplifie rien.

    Dis si tu as besoin de plus d'aide.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #3
    Membre actif
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Octobre 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 330
    Points : 207
    Points
    207
    Par défaut
    Bonjour,

    Merci Tyrtamos pour tes "recettes" qui sont toujours pertinentes . J'ai mis en œuvre ton principe qui fonctionne bien. J'ai fait quelques ajustements afin que le programme principal "attende" la fin du thread de calcul pour poursuivre son propre traitement. J'incorpore dans la procédure déclenchée par le signal de fin du Thread, la mise à jour d'une variable qui redonne la main à la procédure principale
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            # Lancement du Thread de calcul
            simule.start()
            while not self.finCalcul:
                QtGui.QApplication.processEvents()
            # Poursuite de la procédure principale    
            if not self.succes:
            ...
    A part ça, il me reste un souci d'une autre nature. Dans mon Thread de calcul, je lance toute une séquence de calculs et de manipulations de Base de donnée (sqlite) à travers SqlAlchemy. Malheureusement SqlAlchemy n'aime pas trop que l'on manipule des objets qui sont créés dans un autre thread !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sqlalchemy.exc.ProgrammingError: (ProgrammingError) SQLite objects created in a thread can only be used in that same thread.The object was created in thread id 5704 and this is thread id 11792 None [{}]
    Ca m'embête de revoir une bonne partie de la logique de mon appli uniquement pour visualiser un QProgessDialog !

    Question : Existe t-il un moyen de contourner ce problème ? Existe t-il un moyen de laisser le calcul dans la procédure principale et de piloter l'affichage du QProgressDialog dans un autre Thread sachant qu'a priori ça ne se fait pas ...
    L'avantage du QThread sur un threading.Thread() est la capacité de lancer des messages au graphique, car les threads ne peuvent pas, en général, toucher au graphique directement (les bibliothèques graphiques ne sont pas "thread-safe"). On pourrait aussi utiliser une classe avec un héritage multiple threading.Thread + QObjet mais ça ne simplifie rien.
    Merci pour les pistes
    A bientôt

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 461
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 461
    Points : 9 248
    Points
    9 248
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Si à la fin d'un calcul fait dans un QThread, on doit faire une opération dans une base de données interdite dans un thread, je ne vois qu'une solution: que le thread envoie un message (emit) au programme principal (récupéré avec connect), pour que ce programme fasse le boulot. Ce message peut d'ailleurs contenir en même temps des données de résultat.

    Le programme principal peut très bien gérer la liste complexe des opérations que tu destinais au thread. A chaque fois qu'un thread est lancé, on peut attendre son résultat non pas avec .wait() qui gèlerait le graphique, mais avec une boucle d'attente comme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    => lancement du thread de calcul 
    while monthread.isRunning():
        QtGui.QApplication.processEvents()
    => récupération des données renvoyées par le thread à la fin du calcul
    => opération de base de données
     
    => lancement du thread de calcul 
    while monthread.isRunning():
        QtGui.QApplication.processEvents()
    => récupération des données renvoyées par le thread à la fin du calcul
    => opération de base de données
     
    etc...
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Membre actif
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Octobre 2008
    Messages
    330
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 330
    Points : 207
    Points
    207
    Par défaut
    Bonjour,

    En fin de compte j'ai réglé simplement le problème en différenciant, dans le Thread principal et dans le Thread de calcul, les "sessions" déclarées dans SqlAlchemy. Les ajustements sont mineurs j'ai juste l'impression que je perds un peu dans la vitesse de traitement (à vérifier ...).
    Merci pour tes tuyaux,
    @+

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 11/03/2008, 12h25
  2. Réponses: 4
    Dernier message: 16/07/2007, 11h16
  3. Réponses: 1
    Dernier message: 26/06/2007, 10h08
  4. Réponses: 1
    Dernier message: 14/06/2007, 17h28
  5. [VB 6.0] - problème avec Datagrid pour l'affichage de valeurs
    Par jimbololo dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 24/04/2007, 10h57

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