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 :

créer une colonne dynamique


Sujet :

PyQt Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    pilote
    Inscrit en
    Avril 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : pilote
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2012
    Messages : 7
    Points : 5
    Points
    5
    Par défaut créer une colonne dynamique
    Bonjour à tous,

    Le débutant que je suis s’est mis en tête de créer une petite application histoire de mettre les mains dans le cambouis.
    Et je bloc sur un concept depuis plusieurs jours sans trouver de solution.
    L’application dispose de quelques QCombobox et autre QlineEdits insérants entre autre des datetimes dans une BDD sqlite(enfin plutôt du TEXT que je convertis ensuite via un strptime), le tout affiché dans un QTableView, et dans ce QTableView j’ai besoin de soustraire mes dates et afficher le timedelta dynamiquement dans une 3eme colonne:
    Col 1############# Col2##############Col3
    11-04-2018 13:00###11-04-2018 15:00 #######02:00

    C’est donc sur cette cette fameuse 3eme colonne que je bloque.
    Comment faire pour l’afficher de façon dynamique?
    La doc QT evoque bien, entre autre, un QabstractItemModel mais pas d’exemple concret et C++ n’est de pas des plus simple retranscrire en Python.
    N’y aurait il pas un moyen plus simple à l’aide d’un QsqlTableModel que j’utilise deja par ailleurs?


    Le code jusqu’a present:

    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
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtSql import *
    from datetime import datetime
     
    import sys
    import time
    import os
     
    import TabView
     
    from DB_manager import tableModelQtsqlTry
    from DBessai import *
     
     
    # To incorporate UI_view_SARAA inherit QDialog, and UI_view
    class MainDialog(QDialog, TabView.Ui_Dialog):
     
        def __init__(self, parent=None):
            super(MainDialog, self).__init__(parent)
            self.setupUi(self)
            # appel de la classe du module dbessai
            self.LaBase = LaBase()
            self.model = QSqlTableModel()
            self.model.setTable("Contact")
            self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
            self.model.select()
            self.model.setHeaderData(0, Qt.Horizontal, "ID")
            self.model.setHeaderData(1, Qt.Horizontal, "pilot_1")
            self.model.setHeaderData(2, Qt.Horizontal, "datetime1")
            self.model.setHeaderData(3, Qt.Horizontal, "datetime2")
            self.model.setHeaderData(4, Qt.Horizontal, "Calcul")
            self.tableView.setModel(self.model)
     
        def setdata(self):
            query = QSqlQuery()
            query.prepare("INSERT INTO Contact (pilot_1,datetime1,datetime2,total)" "VALUES (?,?,?,?)")
            query.bindValue(0, self.lineEdit_pilote.text())
            query.bindValue(1, self.dateTimeEdit.text())
            query.bindValue(2, self.dateTimeEdit_2.text())
            query.bindValue(3, str(self.get_date_diff()))
            query.exec_()
            self.model.select()
     
        def remove_row(self):
            index = self.tableView.currentIndex()
            deleteconf = QMessageBox.critical(self.parent(), "DELETE ROW", "REALLY DELETE", QMessageBox.Yes,
                                              QMessageBox.No)
            if deleteconf == QMessageBox.Yes:
                self.model.removeRow(index.row())
                self.model.submitAll()
                self.model.select()
                return
            else:
                return
     
        def get_date_diff(self):
            quer = QSqlTableModel(self.model)
            quer.setTable("Contact")
            quer.select()
     
            i = 0
            while i < quer.rowCount():
                time1 = quer.record(i).value("datetime1")
                time2 = quer.record(i).value("datetime2")
                i += 1
                print(type(time1))
                diff = datetime.strptime(time2, "%Y-%m-%d %H:%M") - datetime.strptime(time1, "%Y-%m-%d %H:%M")
                print(diff)
     
     
     
     
     
     
     
        @pyqtSlot()
        def on_calculer_clicked(self):
            str(self.get_date_diff)
     
        @pyqtSlot()
        def on_pushButton_4_clicked(self):
            self.setdata()
     
        @pyqtSlot()
        def on_Effacer_clicked(self):
            self.remove_row()
     
     
    if __name__ == '__main__':
        try:
            app = QApplication(sys.argv)
     
            # create and display splash screen
     
            splash_pix = QPixmap('Logo.png')
     
            splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
            splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
            splash.setEnabled(False)
            # add progress bar
            progressBar = QProgressBar(splash)
            progressBar.setMaximum(10)
            progressBar.setGeometry(0, splash_pix.height() - 50, splash_pix.width(), 20)
     
            splash.show()
            splash.showMessage("<h1><font color='black'>----Bienvenue----</font></h1>",
                               Qt.AlignTop | Qt.AlignCenter, Qt.black)
     
            for i in range(1, 11):
                progressBar.setValue(i)
                t = time.time()
                while time.time() < t + 0.1:
                    app.processEvents()
            # simulating
            time.sleep(1)
            form = MainDialog()
            form.show()
            splash.finish(form)
            app.exec_()
            sys.exit(0)
        except NameError:
            print("Name Error: ", sys.exc_info()[1])
        except SystemExit:
            print("Closing Window....")
        except Exception:
            print(sys.exc_info()[1])

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

    j'ai déjà eu un problème de ce genre. A priori, chacune des colonnes du QTableView doit correspondre à un champ de la table affichée. Donc, à moins qu'il y ait une astuce de Qt5 inconnue de moi (ce qui est possible!), voilà comment j'ai résolu mon problème:

    1- prévoir un champ supplémentaire dans la table de la base sqlite3, qui correspondra à la colonne "dynamique"

    2- créer un TRIGGER (=une "gachette") qui se déclenchera lors des mises à jour (on précise l’évènement qui déclenche) et qui calculera la nouvelle valeur. Valeur qui ira dans la table et sera donc affichée dans le QTableView.

    Pour le TRIGGER, voir ici: http://www.sqlite.org/lang_createtrigger.html .

    sqlite3 a beau n'être qu'aux normes de 1992, on fait avec des chouettes trucs!
    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
    Futur Membre du Club
    Homme Profil pro
    pilote
    Inscrit en
    Avril 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : pilote
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2012
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    salut Tyrtamos,
    La seule réponse qui ressemble à ce dont nous parlons se trouve sur stackoverflow:
    https://stackoverflow.com/questions/...-in-qtableview
    Que penses tu des réponses?
    Comment retranscrire et implémenter cela en pyqt si cela en vaut le coup?

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Puisque c'est le "model" qui établit la liaison entre la base de données et l'affichage dans le QTableView, alors oui, il est possible de sous-classer le modèle utilisé et de surcharger toutes les méthodes concernées pour faire ça. J'ai déjà sous-classé un QSqlRelationalTableModel pour d'autres usages, mais jamais pour ça. Dans la mesure où il y a un exemple sous la main (cf ton lien), il faut essayer! Ce ne sera pas forcément simple à mettre au point, mais c'est intéressant!

    En tout cas, si tu y arrives, je suis intéressé par la solution!

    Et si tu n'y arrives pas, la solution "TRIGGER" est toujours disponible.

    Pour la doc Qt => https://doc.qt.io/qt-5/qsqlrelationaltablemodel.html
    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
    Futur Membre du Club
    Homme Profil pro
    pilote
    Inscrit en
    Avril 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : pilote
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2012
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Salut à tous,

    Avec l'exemple que je citais plus haut, j'ai donc réussit à obtenir le résultat escompté...Le truc c'est donc de surcharger("Override") les méthodes du QSqlTableModel. Et la troisième colonne se met à jour automatiquement avec, pour ce qui me concerne, un time delta.
    Au lieu d'appeler self.data = QSqlTableModel() dans mon __init__ j'appel cette classe donc cela devient self.data = Model() dans le code que j'ai posté précédemment moyennant quelques modifications par ailleurs.
    En espérant que cela puisse servir à d'autres.

    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
    class Model(QSqlTableModel):
        def __init__(self, parent=None):
            super(Model, self).__init__(parent)
            self.setEditStrategy(QSqlTableModel.OnFieldChange)
     
            self.setTable("Contact")
            self.select()
     
        def columnCount(self, parent=QModelIndex()):
            # on ajoute notre colonne virtuelle
            return super(Model, self).columnCount() + 1
     
        def data(self, index, role=Qt.DisplayRole):
            if role == Qt.DisplayRole and index.column() == 4:
                # la 4eme colonne est notre colonne virtuelle
                # si nous sommes dessus nous effectuons notre calcule et la retournons
                # Nous prenons les colonnes qui nous intéresse et effectuons nos operation(ici un calcule de date)
                date2 = self.data(self.index(index.row(),3))
                date1 = self.data(self.index(index.row(),2))
                #premiere facon sans variable
                date2B = datetime.strptime(self.data(self.index(index.row(),3)), "%Y-%m-%d %H:%M")
                #deuzieme facon avec variable(plus lisible)
                date1B = datetime.strptime(date1, "%Y-%m-%d %H:%M")
                return str(date2B - date1B)
     
            if index.column() > 4:
                #si nous passons la 4eme colonne nous devons revenir une colonne en arrière et obtenir le valeur
                index = self.index(index.row(), index.column() - 1)
            # retourne le valeur de la "base implementation
            return super(Model, self).data(index, role)
     
        def headerData(self, section, orientation, role=Qt.DisplayRole):
            # meme chose que data
            if section == 4 and orientation == Qt.Horizontal and role == Qt.DisplayRole:
                return 'Sum'
            if section > 4 and orientation == Qt.Horizontal:
                section -= 1
            return super(Model, self).headerData(section, orientation, role)
     
        def flags(self, index):
            # Notre 4eme colonne ne sera pas editable les autres pourrons l'être 
            if index.column() == 4:
                return Qt.ItemIsSelectable | Qt.ItemIsEnabled
            return Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
     
        def setData(self, index, data, role):
            # meme chose que pour Data
            if index.column() > 4:
                index = self.index(index.row(), index.column() - 1)
            return super(Model, self).setData(index, data, role)

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

    Merci pour la solution, heliomaster, et bravo!
    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

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

Discussions similaires

  1. [VBA/VB] créer une page dynamiquement dans un WebBrowser
    Par SilkyRoad dans le forum Contribuez
    Réponses: 3
    Dernier message: 13/03/2013, 22h24
  2. Comment créer une colonne dynamique d'items ?
    Par Masamunai dans le forum VB.NET
    Réponses: 19
    Dernier message: 04/12/2010, 19h11
  3. [Tableaux] Créer une ligne dynamiquement
    Par Lenaick dans le forum Langage
    Réponses: 11
    Dernier message: 24/01/2007, 10h58
  4. [WebForms]créer une formulaire dynamiquement
    Par lamiae18 dans le forum Général Dotnet
    Réponses: 1
    Dernier message: 16/01/2007, 18h43
  5. Réponses: 2
    Dernier message: 17/11/2006, 07h29

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