Partage
  • Partager sur Facebook
  • Partager sur Twitter

QTableView et Delegate

    18 novembre 2013 à 11:50:29

    Bonjour

    J'utilise des Delegate pour l'affichage de mon QTableView. Et çà marche bien, sauf que je suis obligé de double cliquer sur la cellule de mon QtablView pour avoir le résultat.

    Exemple, j'ai un délégate qui me permet de colorer le texte d'une cellule en fonction de sa valeur. Ca marche, mais il faut que je double clique dessus pour voir la couleur (c'est ball lol).

    Idem pour un QComboBox, de base je vois la valeur, mais pour activer la liste déroulante, il faut que je double clique dessus.

    Voici les deux Delegate que je me suis fais, pouvez vous me dire ce qu'ils leur manque?

    Pour le QComboBox :

    class CategorieDelegate(QtGui.QItemDelegate):
     
        def __init__(self, owner):
            QtGui.QItemDelegate.__init__(self, owner)
            
            #On charge TOUTES la table "Categories" dans le model
            self.modelCategorie = QSqlTableModel(self)
            self.modelCategorie.setTable("Categories")
            self.modelCategorie.select()
    
    
        def createEditor(self, parent, option, index):
            
            if index.data(QtCore.Qt.DisplayRole).toString() != '':
                text = index.data(QtCore.Qt.DisplayRole).toString()
                editor = QtGui.QComboBox(parent)
                editor.setModel(self.modelCategorie);
                editor.setModelColumn(self.modelCategorie.fieldIndex("name"))
                indexCat = editor.findText(unicode(text))
                editor.setCurrentIndex(indexCat)
                editor.installEventFilter(self)         
                return editor
            else:
                editor = QtGui.QLabel(parent)
                editor.setText(u'Virement')
                return editor
    
     
        def setEditorData(self, editor, index):
            if index.data(QtCore.Qt.DisplayRole).toString() != '':
                value = index.data(QtCore.Qt.DisplayRole).toString()
                indexCat = editor.findText(unicode(value))
                editor.setCurrentIndex(indexCat)
            else:
                editor.setText(u'Virement')
     
        def setModelData(self,editor,model,index):
            if index.data(QtCore.Qt.DisplayRole).toString() != '':
                value = editor.currentIndex()
                myIndex = self.modelCategorie.index(value, 0)
                categorieId = self.modelCategorie.data(myIndex, 0).toInt()[0]
                #Enregistrement
                model.setData(index, QtCore.QVariant(categorieId))

    pour le text

    class MontantDelegate(QtGui.QItemDelegate):
     
        def __init__(self, parent):
            QtGui.QItemDelegate.__init__(self, parent)
            self.parent = parent
    
        def createEditor(self, parent, option, index):
            editor = QtGui.QLineEdit(parent)
            val  = index.data(QtCore.Qt.DisplayRole).toInt()[0]
            if val > 0:
                editor.setStyleSheet("QLineEdit { color : green;}")
            else:
                editor.setStyleSheet("QLineEdit { color : red;}")
            return editor
    
        def setEditorData(self, editor, index):
            value = index.data(QtCore.Qt.DisplayRole).toInt()[0]
            editor.setText(str(value))
    
        def setModelData(self,editor,model,index):
            value = editor.text()
            model.setData(index, value)
            model.submitAll()
    
            #En cas de virement, on doit mettre à jour les deux enregistrements.
            row = index.row()
            if model.index(row, 14).data().toInt()[1] == True:
                idVirement = model.index(row, 14).data().toInt()[0]
                query = QSqlQuery()
                query.exec_('UPDATE Operations\
                             SET montant = '+str(value)+'\
                             WHERE (virement_id = '+str(idVirement)+')')
                #print query.lastError().text()
    
            currentBudgetId = self.parent.Settings.value("currentBudgetId").toInt()[0]
            self.parent.loadAccountTableWidget(currentBudgetId)

    Merci d'avance pour votre aide. Je suppose que ce n'est pas grand chose, mais je tourne en rond.

    ;)


    • Partager sur Facebook
    • Partager sur Twitter
      18 novembre 2013 à 12:01:29

      Il faut que tu redéfinisses la méthode paint().

      -
      Edité par Erd 18 novembre 2013 à 12:02:41

      • Partager sur Facebook
      • Partager sur Twitter
        18 novembre 2013 à 13:55:25

        Arfff, c'est ce que je pensais, mais que je redoutez. J'ai encore vraiment beaucoup de mal avec les delegate et encore plus avec la méthode pain() que je ne comprend pas.

        j'ai essayé çà pour le delegate de mon QComboBox

        def paint(self, painter, option, index):        
                # Get Item Data
                value = index.data(QtCore.Qt.DisplayRole).toString()
                # value = self.itemslist[index.data(QtCore.Qt.DisplayRole).toInt()[0]]
                # fill style options with item data
                style = QtGui.QApplication.style()
                opt = QtGui.QStyleOptionComboBox()
                opt.currentText = value
                opt.rect = option.rect
                # draw item data as ComboBox
                style.drawComplexControl(QtGui.QStyle.CC_ComboBox, opt, painter)
                #self.parent.openPersistentEditor(index)

        Il me dessine effectivement une liste déroulante, mais vide… et je ne trouve pas la doc pour m'aider avec les méthodes qui sont associé au QStyleOptionComboBox(). La j'utilise currentText() j'ai pas de message d'erreur, mais ça reste vide...

        • Partager sur Facebook
        • Partager sur Twitter
          18 novembre 2013 à 14:12:04

          Ton code permet de dessiner l'apparence des QCombobox (qui sont vides par défaut). Il faut lui ajouter le code pour dessiner le texte à afficher. Du coup, il faut simplement ajouter un appel à QPainter::drawText().

          Tu peux aussi carrément créer un QCombobox qui contient uniquement un item (ton texte) et utiliser la méthode QWidget::render() pour dessiner le rendu dans ta case. C'est un peu plus lourd niveau exécution mais plus radical...

          • Partager sur Facebook
          • Partager sur Twitter
            18 novembre 2013 à 14:33:47

            Erd a écrit:

            Du coup, il faut simplement ajouter un appel à QPainter::drawText().

            Super, merci!

            Ok, ça semble bien, sauf que : Comment on utilise drawText(), avec les messages d'erreurs je vois qu'il faut dire 'ou l'on doit écrire le text et pour cela on à le choix entre :QPointF, QrectF ou QPoint (et des entiers)

            Le hic c'est que je ne sais pas ou l'on récupère la position?

            • Partager sur Facebook
            • Partager sur Twitter
              18 novembre 2013 à 14:46:01

              La position est donnée par ton option.rect.

              • Partager sur Facebook
              • Partager sur Twitter
                18 novembre 2013 à 14:51:40

                je venez juste de trouver lol

                painter.drawText(option.rect, Qt.AlignVCenter, str(value))

                sauf que j'ai toujours le même problème. La liste est grisé et il faut que je double clique dessus pour la rendre active. Un simple clique sélectionne la cellule du QTableView et il faut un double clique pour activer ce qu'il y a dedans...

                Des idées? C'est peut être du à mon QtableView est non au Delegate?

                • Partager sur Facebook
                • Partager sur Twitter
                  18 novembre 2013 à 14:57:08

                  Il faut changer le EditTrigger de ta vue pour déclencher l'édition avec un simple clic.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    18 novembre 2013 à 15:34:12

                    j'ai changé pour 

                    tableView.setEditTriggers(QtGui.QTableView.AllEditTriggers)
                    

                    C'est un peu mieux, deux simple clique permettent d'activer la liste mais ça ne marche toujours pas du premier coup. Il faut activer la cellule, puis cliquer encore une fois dedans… arffff

                    • Partager sur Facebook
                    • Partager sur Twitter
                      20 novembre 2013 à 13:41:00

                      En plus avec : AllEditTriggers mon clique droit ne marche plus (car cellule active..) bref je vais garder le double clique. On vera ça plus tard ;)

                      • Partager sur Facebook
                      • Partager sur Twitter
                        29 août 2014 à 23:46:36

                        Ce topic date un peu mais je l'enrichis pour les gens qui auraient le même problème:

                        plutot que de réimplémenter la méthode paint, on peut simplement réimplémenter la méthode

                        initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const
                        


                        le pointeur option permet de modifier la vue du widget, donc pour mettre un texte initial (avant que l'éditeur ici une QComboBox ne s'ouvre), il suffit de faire

                        initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const
                        {
                            if(index.column()!=2)
                                return QStyledItemDelegate::initStyleOption(option, index);
                        
                            option->text = "Text initial";
                        
                        }

                        Dans mon exemple, j'invalide les index qui ne concernent pas la QComboBox (ici toutes colonnes dont le rang n'est pas 2)

                        En espérant aider quelqu'un...

                        • Partager sur Facebook
                        • Partager sur Twitter

                        QTableView et Delegate

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown