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 :

QTreeView rempli avec QAbstractItemModel


Sujet :

PyQt Python

  1. #1
    Membre averti

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Mars 2017
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2017
    Messages : 13
    Par défaut QTreeView rempli avec QAbstractItemModel
    Bonjour,

    Je réalise une petite application pour visualier le travail fait par un groupe de personne. Chaque personne peut travailler sur plusieur OF (Ordre de Fabrication) dans une journée. Et pour chaque OF de cette personne, je souhaite pouvoir développer une liste avec d'autre information.

    Je m'intéresse donc à la création d'un arbre. J'ai suivi la doc de Qt5. Les données s'affichent: 2 lignes pour les 2 opérateurs que je test. Mais quand je veux déployer la liste, je retrouve les mêmes données.

    J'ai créé les données comme un table à plusieurs dimensions:
    [Opérateur, [Info OF1, Info OF2]]

    et Info OF: [OF,Dt début, Dt fin, type fin]

    La structure n'ai pas reconnu comme une hierarchie, la documentation parle bien de parent --> enfant, mais je ne vois pas comment le mettre en oeuvre lors du chargement des données.

    Voici la déclaration de QAbstractItemModel:
    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
    62
    63
    64
    65
    66
     
    class ModelOFOP(QtCore.QAbstractItemModel):
        def __init__(self,*args, LsChrono = None, **kwargs):
            super(ModelOFOP,self).__init__(*args,**kwargs)
     
            #Arrangement des données de façon heirarchique:
            # Utilisateur: poste : opération (Séquence|Multi, début, fin)
            #La liste est triée par ordre chronologique et utilisateur.
            self.LsOFOP=[]
     
            #Données temporaires:
            CrtUt = None
            CrtSeq = None
     
            print(LsChrono,sep='\n',end='\n\n')
     
            #Mappage des données (à changer si évolution de la requête)
            self.DataMap = {"ID_User":3,
                       "Seq":1,
                       "Chrono":2,
                       "Multi":5,
                       "Event":4}
     
            for row in LsChrono:
                #Passe à un autre opérateur
                if CrtUt != row[self.DataMap["ID_User"]]:
                    self.LsOFOP.append([row[self.DataMap["ID_User"]]])
                    CrtUt = row[self.DataMap["ID_User"]]
                #Début d'une séquence:
                if row[self.DataMap["Event"]] == 0:
                    self.LsOFOP[-1].append([row[self.DataMap["Seq"]],row[self.DataMap["Chrono"]],None,None])
                #Autre cas: arrêt de la séquence
                else:
                    #Enregistre heure de fin
                    self.LsOFOP[-1][-1][2]=row[self.DataMap["Chrono"]]
                    #Enregistre événement de fin
                    self.LsOFOP[-1][-1][3]=row[self.DataMap["Event"]]
            print(self.LsOFOP,sep='\n',end='\n\n')
     
        def data(self,index, role):
            if role == Qt.DisplayRole:            
                if index.column() == 0:
                #Opérateur, à remplacer par le Nom prénom à terme
                    print("Colonne 0: %s"%self.LsOFOP[index.row()][0])
                    return self.LsOFOP[index.row()][0]
                elif index.column() == 1:
                    print("Colonne 1: %s"%self.LsOFOP[index.row()][1][0])
                    return self.LsOFOP[index.row()][1][0]
                elif index.column() == 2:
                    print("Colonne 2: %s"%self.LsOFOP[index.row()][1][1])
                #Renvoi début, fin et événément
                    return self.LsOFOP[index.row()][1][1]
     
        def rowCount(self,index=None):
            return len(self.LsOFOP)
     
        def columnCount(self,index = None):
            return len(self.DataMap)
     
        #Re définition fonction index
        def index(self,row,column,parent=QModelIndex()):
            return self.createIndex(row,column,parent)
     
        #Un seul parent en colonne 0
        def parent(self,child):
            return self.index(child.row(),0)

    Nom : Capture Liste OFOP.JPG
Affichages : 749
Taille : 23,4 Ko

    Je me doute que ça doit se faire dans la boucle d'enregistrement des données dans l'arbre, mais je ne vois pas comment déclarer le premier parent et les enfants. Pas trouvé de tuto claire sur les arbres non plus.

    Si vous avez des pistes. Merci.

    Alexis

  2. #2
    Membre averti

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Mars 2017
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2017
    Messages : 13
    Par défaut Solution alternative avec QStandardItemModel
    Bonjour,

    Pour me faire les dents, j'ai alimenté mon QTreeView avec un QStandardItemModel.
    Dans ce cas, j'ai pu trouvé un peu plus de document pour utiliser les fonctions d'ajout d'enfants. Mais c'est quand même un peu la devinette!!

    Ce qui peut être surprenant en lisant la documentation:
    - on ajout une entrée à la liste avec "appendRow" et un Item qui devien un enfant de 1er niveau.
    - poura jouter des ifnormations à afficher, ça se fait avec setData pour un parent (le 1er niveau) et avec setChild par la suite.
    - j'ai pas réussi à passer un tableau directement pour remplir une ligne. setChild attend un objet Item qui n'a qu'un élément. Et c'est ce dernier Item qui contient les infos à afficher.

    Pas super claire hein? Bon alors voici le code et ce que ça donne
    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
    def MajVueOFOp(self):
            #Chargement des données depuis fichier teste
            #TODO: depuis BD
            try:
                with open(os.path.join(dir_path,'data','Data_Event.csv')) as f:
                    dataListe = json.load(f)
            except Exception as err:
                print("Erreur chargement fichier donnée %s"%err)
                return -1
     
            self.DataMap = {"ID_User":3,
                               "Seq":1,
                               "Chrono":2,
                               "Multi":5,
                               "Event":4}
     
            #Création du model à partir à partir de QStandrdItemModel pour avoir une arborescence
            self.ArbreOFOp = QStandardItemModel(0,5)
            parentItem = self.ArbreOFOp.invisibleRootItem()
     
            #Par cour le ficher pour construire le modéle
            CrtUt = None
            for row in dataListe:
                #Passe à un autre opérateur
                if CrtUt != row[self.DataMap["ID_User"]]:
                    enfantOp=QStandardItem()
                    enfantOp.setData(row[self.DataMap["ID_User"]],Qt.DisplayRole)
                    parentItem.appendRow(enfantOp)
                    #parentItem.setChild(parentItem.rowCount(),0,item)
                    CrtUt = row[self.DataMap["ID_User"]]
     
                #Début d'une séquence:
                if row[self.DataMap["Event"]] == 0:
                    #Declare un nouveau fils avec une ligne et 4 colonnes:
                    items = QStandardItem(1,4)
     
                    #Ce nouveau fils sera ajouté à la derniére ligne enfant:
                    DerLigne = enfantOp.rowCount()
     
                    #Ajout des données aux colonnes, à partir de la 1
                    MyData = (str(row[self.DataMap["Seq"]]),str(row[self.DataMap["Chrono"]]),"","")
                    for col in range(0,len(MyData)):
                        item = QStandardItem(MyData[col])
                        enfantOp.setChild(DerLigne,col+1,item)
    Nom : Capture liste Ok.JPG
Affichages : 680
Taille : 19,7 Ko

    Mais dans ce cas, je vois pas trop l'intérêt d'une approche model de données: je suis obligé d'afficher toutes les données de mon model! Hors il y a des infos qui ne vont rien dire à l'utilisateur. Par exemple: l'ID de l'utilisateur, je doit afficher sont nom et prénom et garder sont ID dans le model. Ou encore le datetime de début: afficher uniquement les heures et les minutes tout en gardant le reste des données intactes.

    Quel est l'intérêt de cette classe QStandardItemModel et un QTreeView par rapport à un QTreeWidget?

    Alexis

  3. #3
    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

    Citation Envoyé par Alex157 Voir le message
    Quel est l'intérêt de cette classe QStandardItemModel et un QTreeView par rapport à un QTreeWidget?
    Je me pose la même question.

    Une classe "Q...View" devrait établir une liaison automatique entre la partie graphique et la partie donnée grâce à un modèle. Avec un QTreeView branché sur un disque dur grâce au modèle QFileSystemModel, ça marche très bien! Mais dans les autres cas, il devrait y avoir une structure de données bien définie pour ça (une liste de listes?) en rapport avec le modèle, mais je ne la trouve pas.

    Avec d'autres classes comme les QTableView, on peut se brancher sur une base de données (avec un pilote) pour gérer une table, et ça marche très bien aussi: la modification des données affichées se répercutent bien sur la base de données.

    Alors, au lieu du QTreeView, je préfère le QTreeWidget.

    C'est dommage que ce ne soit pas plus clair, car la gestion d'un arbre est assez courante et même d'assez universelle: on devrait avoir un outil plus facile et plus pratique pour faire ça...

    Mais peut-être quelqu'un a-t-il ici une meilleure connaissance du sujet?

Discussions similaires

  1. [Conception]champs numerique rempli avec du texte
    Par milielf dans le forum Modélisation
    Réponses: 6
    Dernier message: 03/04/2007, 13h39
  2. Réponses: 4
    Dernier message: 22/01/2007, 19h51
  3. [MySQL] Tableau rempli avec une requête
    Par jolonghorn dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 02/01/2007, 19h39
  4. Formulaire pré rempli avec info de la bdd
    Par dolf13 dans le forum Langage
    Réponses: 8
    Dernier message: 12/07/2006, 11h50
  5. [Struts]Select rempli avec un intervalle de nombre
    Par worldchampion57 dans le forum Struts 1
    Réponses: 1
    Dernier message: 13/04/2006, 10h21

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