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 :

Affichage utilisateur pendant le (long) démarrage de mon application


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    Mai 2010
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mai 2010
    Messages : 313
    Par défaut Affichage utilisateur pendant le (long) démarrage de mon application
    Bonjour,

    je développe une application PyQt4 qui doit commencer par récupérer tout le contenu et la structure de la base de données de mon site internet.
    Pour cela, j'ai créé un fichier php dédié que j'ai mis sur mon serveur, et j'appelle cette page depuis mon appli python grâce à urllib2.urlopen et urllib2.Request.

    Je récupère ensuite le texte html créé afin d'en extraire les résultats de ma requête. Au démarrage de mon application, je lance donc une série de requêtes afin d'obtenir le nom des tables de la base, et pour chaque table le nom des champs qui la composent et toutes les données.

    Voici mon code:

    Extrait de la méthode __init__ de mon application:
    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
    # Recuperation de la liste des tables (noms)
        requeteListeTables= RequeteSQL.RequeteSQL(self.parametres.url, 'lireStructure')
        self.nomsTables= requeteListeTables.executer()
     
        #Creation de self.tables, tableau d'objets Table
        self.tables = []
        for nomTable in self.nomsTables:
            # Creation d'une nouvelle Table
            newTable = Table.Table(nomTable)
     
            # Recuperation de la liste des champs de la table
            requeteChampsTable = RequeteSQL.RequeteSQL(self.parametres.url, 'lireStructure', nomTable)
            listeChamps = requeteChampsTable.executer()
     
             # Recuperation des donnees pour chaque champ de la table   
             for nomChamp in listeChamps:
                 requeteDonneesChamp = RequeteSQL.RequeteSQL(self.parametres.url, 'lireDonnees', nomTable, nomChamp)
                 listeDonnees = requeteDonneesChamp.executer()
                 newTable.champs[nomChamp] = listeDonnees
            self.tables.append(newTable)
    classe Table:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Table():
        ''' Table: represente une table de la base de donnees '''
        def __init__(self, nomTable):
            '''
            Constructeur de la classe Table
            nomTable: (str) nom de la table correspondante dans la base de donnees
            '''
            self.nom = nomTable
            self.champs = {}
    classe RequeteSQL:
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    class RequeteSQL():
        ''' RequeteSQL: generation et execution de requetes SQL sur la base de donnees '''
        def __init__(self, url, action, table=None, champ=None, id=None):
            '''
            Constructeur de la classe RequeteSQL
            url: adresse du fichier "gestionBDD.php" du site
            action: (str) type de requete a effectuer
            table: (objet Table - factultatif) table concernee
            champ: (str - factultatif) champ de la table concerne
            id: (int - facultatif) identifiant de l entree de la table concerne
            '''
            self.url = url
            self.action = action
            self.table = table
            self.champ = champ
            self.id = id
            self.resultat = []
            self.requete = ''
            self.generer()
     
        def generer(self):
            '''
            Generere le texte correspondant a la requete demandee
            '''
            if self.action == 'lireStructure':
                if self.table is None:
                    self.requete = "lire.all"
                else:
                    self.requete = 'lire.' + self.table
     
            elif self.action == 'lireDonnees':
                self.requete = 'lire.%s.%s'%(self.table, self.champ)
                if self.id is not None:
                    self.requete = self.requete + '.' + self.id
     
        def executer(self):
            '''
            Appel a la page php definie par self.url avec la requete a effectuer
            Recuperation des resultats dans le texte html ainsi genere
            '''
            # Execution de la requete: genere une page HTML avec les resultats (dans string "resultRequete")
            try:
                resultRequete = urllib2.urlopen(urllib2.Request(self.url + '?requete=' + self.requete, None, {'User-Agent': 'MyBrowser/0.1'})).read()
            except urllib2.HTTPError:
                return "la page specifiee: %s est introuvable"%(self.url,)
     
            # Extraction des resultats
            m = re.split('<separator>', resultRequete)
            if len(m) == 0:
                return "La requete n'a pu etre executee"
            else:
                m.pop(0)
                if len(m) > 0:
                    m.pop()
                if len(m) == 0:
                    return "La requete a renvoye une chaine vide"
                elif len(m)==1 and m[0].startswith('ERREUR'):
                    return m[0]
                else:
                    self.resultat = m
                    return self.resultat
    Mon problème est que cela prends pas mal de temps, environ 10s par table pour tout récupérer... Je ne suis pas sure de pouvoir réduire ce temps, mais je voudrais au moins afficher une fenêtre avec l'état d'avancement afin que l'utilisateur sache où en est l'application.

    J'ai vu qu'on pouvait utiliser des QThread pour gérer l'affichage d'une fenêtre Qt tout en effectuant d'autres tâches, mais je ne comprends pas trop comment cela fonctionne
    Peut-être y a t-il aussi moyen de réduire le temps d'execution? Je vous remercie d'avance pour toute aide ou idée que vous pourriez m'apporter

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    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 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    On peut tout à fait utiliser QThread pour charger les données, ce qui permet pendant ce temps de ne pas avoir l'ihm figée. Mais QThread ne peut pas piloter lui-même le graphique. Il ne doit même pas y toucher (sinon: plantage aléatoire à prévoir).

    Ce qu'on fait dans ce cas-là, c'est:
    - quand il le faut, le QThread envoie un message (emit)
    - le graphique principal reçoit le message (connect) et fait ce qui est prévu, par exemple mettre à jour une barre de progression.
    - on peut avoir un second type de message qui, lui, indique que le chargement est terminé.

    Pour ce qui est de la barre de progression, il y a 2 situations différentes:
    - on sait chiffrer et alimenter une progression de 0 à 100% => cas courant
    - ou on ne sait pas => on programme alors une "chenille" pour indiquer que l'activité est en cours. Dans ce cas, on a seulement besoin d'un message de fin.

    Si tu coince là-dessus, dis-le et je te monterais un petit exemple.

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 776
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 776
    Par défaut
    Salut,
    Regardez aussi le widget QSplashScreen: il est dédié a çà.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre très actif
    Inscrit en
    Janvier 2004
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 208
    Par défaut
    salut

    j'ai du mal a suivre pourquoi la génération d'une page a balisage html.
    Il ne serait pas plus simple de ressortir le tout formater en Json.

    Le gain de temps avec ce format sera considérable pour les échanges.

    PHP gérè très bien le format Json, et je pense que python doit aussi très bien gérer ce format, tu as l'api Json.

  5. #5
    Membre éclairé
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    Mai 2010
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mai 2010
    Messages : 313
    Par défaut
    Merci pour vos réponses,
    effectivement QSpalshScreen correspond bien à mon cas, j'importe donc maintenant ma base de données avant de démarrer l'IHM, en affichant l'avancement sur mon splashScreen, ça marche très bien!
    Merci
    Je ne vais donc finalement pas utiliser les QThread. J'ai également ajouté une barre de progression à mon spalsh screen:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pixmap = QPixmap("splashScreen.png") # image 480x320
    self.splashScreen = QSplashScreen(pixmap, Qt.WindowStaysOnTopHint)
    self.progressBar = QProgressBar(self.splashScreen)
    self.progressBar.setGeometry(48, 256, 384, 32)
    Ensuite je n'ai plus qu'à reprendre le code où je récupère les infos de ma base de données, en ajoutant des messages et en faisant avancer ma barre de progression avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    self.splashScreen.showMessage(u"Message")
    self.progressBar.setValue(avancement)
    self.app.processEvents()
    J'ai regardé pour les objets Json, ça à l'air intéressant et je vois bien comment créer un objet Json dans ma page php, mais comment le transmettre ensuite à mon programme Python? Avec urllib2.ulropen, je récupère le code html renvoyé par la page, comment avoir l'objet Json à la place?

    Merci encore!

    EDIT: Tyrtamos je n'ai pas besoin des QThread pour ce cas, mais j'en aurai besoin pour un autre projet, je créerai une discussion là-dessus dans quelques temps!

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 776
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 776
    Par défaut
    Citation Envoyé par mokochan Voir le message
    J'ai regardé pour les objets Json, ça à l'air intéressant et je vois bien comment créer un objet Json dans ma page php, mais comment le transmettre ensuite à mon programme Python? Avec urllib2.ulropen, je récupère le code html renvoyé par la page, comment avoir l'objet Json à la place?
    La requête http est une commande GET _sur_ une URL qui retourne du HTML par défaut.
    Vous pourriez ajouter une "URL"-Json pour récupérer la même chose en JSON.

    Plus propre: plutôt que de créer autant d'URL que de format HTML, JSON, ... Vous précisez le format souhaite dans les attributs de la requête GET: c'est cote "serveur-http" qu'on dispatche le get en fonction du format. Les modalités de réalisation dépendent du framework et de l'existant cote "appli".

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

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

Discussions similaires

  1. erreur lors du démarrage de mon application vb.net
    Par lucaazori1988 dans le forum VB.NET
    Réponses: 1
    Dernier message: 16/10/2010, 21h13
  2. Faire patienter l'utilisateur pendant un long traitement
    Par M E H D I dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 20/05/2010, 11h46
  3. Séquence de démarrage de mon application
    Par sousou88 dans le forum Débuter
    Réponses: 3
    Dernier message: 21/02/2010, 20h08
  4. afficher une image au démarrage de mon application ?
    Par kohan95 dans le forum NetBeans
    Réponses: 23
    Dernier message: 19/06/2009, 13h09
  5. Réponses: 7
    Dernier message: 11/08/2008, 19h12

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