2010-09-28 13 views
0

tout d'abord, im nouveau à python et pyqt alors s'il vous plaît ours avec moi. Im utilisant un QTableView avec un QSqlTableModel tout fonctionne comme prévu. La dernière colonne de la vue contient seulement 0 et 1 comme valeur que je veux afficher comme case à cocher et cette colonne devrait être éditable.Impossible d'obtenir un ItemDelegate personnalisé au travail

J'ai lu que vous devriez sous-classer QItemDelegate ce que j'ai fait. Malheureusement ma table ne montrera pas la dernière colonne comme une case à cocher.

J'ai essayé de définir le délégué uniquement pour la dernière colonne (comme je le voudrais) en utilisant setItemDelegateForColumn(), cela ne fonctionnait pas. Je l'ai donc modifié et défini pour l'ensemble de QTableView en utilisant setItemDelegate() en ne réagissant qu'aux requêtes à la dernière colonne. Cela ne marchera toujours pas. Wont travail signifie qu'il n'y a pas de messages d'erreur, il ne fera pas ce que je dis;) Il semble qu'aucune des méthodes que j'ai réimplémenté ne soit jamais appelée, sauf init(). Donc je suppose que je manque quelque chose de fondamental. Après avoir extrait les lignes de code pertinentes, KSCheckBoxDelegate est ma sous-classe. C'est la version où le délégué est configuré pour l'ensemble de QTableView.


-- code from applications main class -- 
self.taglist = QTableView() 
self.tagmodel = QSqlTableModel() 
self.tagmodel.setTable("data") 
self.tagmodel.select() 
self.taglist.setModel(self.tagmodel) 
print self.taglist.itemDelegate() 
myDel = KSCheckBoxDelegate(self) 
myDel.colnumber = 3 
self.taglist.setItemDelegate(myDel) 


-- KSCheckBoxDelegate.py -- 
from PyQt4.QtGui import * 

class KSCheckBoxDelegate(QStyledItemDelegate): 

    colnumber = None 

    def __init__ (self, parent = None): 
     print "KSCheckBoxDelegate::init" 
     QStyledItemDelegate.__init__(self, parent) 

    def createEditor(self, parent, option, index): 
     print "KSCheckBoxDelegate::createEditor" 
     if index.column()==self.colnumber: 
      return QCheckBox(self) 
     else: 
      return QStyledItemDelegate.createEditor(self, parent, option, index) 

    def setEditorData (self, editor, index): 
     print "KSCheckBoxDelegate::setEditorData" 
     if index.column() == self.colnumber: 
      cont = index.model().data(index, Qt.DisplayRole).toString() 
      if cont == "1": 
       editor.setCheckState(Qt.Checked) 
      else: 
       editor.setCheckState(Qt.UnChecked) 
     else: 
      QStyledItemDelegate.setEditorData(self,editor, index) 

    def setModelData (self, editor, model, index): 
     print "KSCheckBoxDelegate::setModelData" 
     if index.column() == self.colnumber: 
      if editor.checkBox.checkState() == Qt.Checked: 
       model.setData(index, 1) 
      else: 
       model.setData(index, 0) 
     else: 
      QStyledItemDelegate.setModelData(self, editor, model, index) 

Des indices pour moi sur ce problème?

En outre, j'ai des difficultés avec le signal currentChanged() du modèle de sélection QTableViews. Im en imprimant les coordonnées en haut à droite de la sélection. Je continue à obtenir des index erronés (non invalides) lorsque je clique avec le bouton gauche de la souris. En utilisant les touches du curseur me donne les bons index. L'utilisation de selectionChanged() a le même comportement. Je suis en train d'obtenir les coordonnées de la seconde dernière cellule sélectionnée de QTableView. Par exemple im en cliquant sur les coordonnées < 1,1> < 2,1> le deuxième clic me montrerait les coordonnées < 1,1>.


selInd = self.taglist.selectionModel().selectedIndexes() 
if(len(selInd) > 0): 
    self.xPosData=selInd[0].column() 
    self.yPosData=selInd[0].row() 

fixe par moi-même, avec l'aide QTableView.currentIndex() au lieu de selectionModel.selectedIndexes() :)

et dernier arrêt à l'aide OnManualSubmit comme editStrategy ne marche pas jeter une erreur (return false) lorsque appelant submitAll() mais ne sauvegarde pas les données non plus. Cela fonctionne avec choisir OnFieldChange comme editStrategy. Ce que je peux vivre avec mais ce n'est pas ce que j'avais l'intention de faire.

Merci pour votre temps.

Horst

+0

Juste un commentaire ici pour ne pas confondre sélectionnés et indices actuels, et d'utiliser celui que vous voulez vraiment. Selon votre modèle de sélection, l'index actuel pourrait très facilement ne pas être sélectionné, et (comme vous l'avez vu) les index sélectionnés peuvent ne pas inclure l'index actuel. –

Répondre

1

Je pense qu'il serait plus simple de créer votre propre modèle basant QSqlTableModel, et pour votre colonne 0/1 retour QVariant() pour QDisplayRole et retour Qt :: Vérifié/Qt :: Qt pour Décoché: : CheckStateRole en fonction de la valeur. Pour tous les autres cas retourner les données de QSqlTableModel

class MySqlTableModel: public QSqlTableModel 
{ 
public: 
// contructors 
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) 
    { 
     if(index.column() == 3 /* your 0/1 column */) 
     { 
      if(role == Qt::DisplayRole) 
      { 
       return QVariant(); 
      } 
      else if(role == Qt::CheckStateRole) 
      { 
       QString value = QSqlTableModel::data(index, Qt::DisplayRole).toString(); 
       return value == "1" ? Qt::Checked : Qt::Unchecked; 
      } 
     } 

     return QSqlTableModel::data(index, role); 
    } 
}; 

Je sais que c'est le code C++, mais la logique est toujours même, donc réadapter juste pour Python

+0

Juste une courte mise à jour et une autre question, je suis de retour pour appliquer le délégué seulement à la colonne, après avoir commencé mon application cette colonne stil, montre 0 et 1 MAIS si je double clique sur une cellule im obtenir une case à cocher qui représente les valeurs correctement. Malheureusement, je ne peux pas modifier la case (elle n'est pas cliquable). Dois-je dériver mon propre modèle et surcharger la méthode flags()? Je l'ai fait en vain:/En outre, je pense maintenant que j'ai besoin de réimplémenter la méthode paint() de mon délégué pour l'avoir montrer les cases à cocher, est-ce exact? –

+0

Avez-vous essayé ma solution? –

+0

Je l'ai essayé Kamil, merci pour vos efforts. Malheureusement, je n'ai pas mage pour le mettre dans un état de fonctionnement:/- Im en cours d'exécution avec un QSQLTableModel, un QItemDelegate affecté à la colonne 3 et cela fonctionne :) Je manque seulement la possibilité d'éditer les cases à cocher atm. –

0

au moins je réussi à avoir mes cases à cocher Afficher des délégués avec le état correct en mode d'affichage et d'édition. Parce que je ne pouvais pas trouver une description complète sur la façon de le faire mal le partager. Peut-être que d'autres personnes essayant de faire quelque chose de similaire sans avoir travaillé avec qt jamais auparavant.Une seule chose est manquante, c'est que les éléments étant modifiables, je suppose que c'est lié à la question des drapeaux que j'ai demandé dans mon post d'ouverture.

- KSCheckBoxDelegate.py -


class KSCheckBoxDelegate(QStyledItemDelegate): 
    def __init__ (self, parent = None): 
     print "KSCheckBoxDelegate::init" 
     QStyledItemDelegate.__init__(self, parent) 

    def createEditor(self, parent, option, index): 
     print "KSCheckBoxDelegate::createEditor" 
     return QCheckBox(parent) 

    def setEditorData (self, editor, index): 
     print "KSCheckBoxDelegate::setEditorData" 
     cont = index.model().data(index, Qt.DisplayRole).toString() 
     if cont == "1": 
      editor.setCheckState(Qt.Checked) 
     else: 
      editor.setCheckState(Qt.Unchecked) 

    def setModelData (self, editor, model, index): 
     print "KSCheckBoxDelegate::setModelData" 
     if editor.checkState() == Qt.Checked: 
      model.setData(index, 1) 
     else: 
      model.setData(index, 0) 

    def paint (self, painter, option, index): 
     myopt = QStyleOptionViewItemV4(option) 
     newopt = QStyleOptionButton() 
     newopt.rect = myopt.rect 
     newopt.palette = myopt.palette 
     if index.data().toBool(): 
      newopt.state |= QStyle.State_On 
     QApplication.style().drawControl(QStyle.CE_CheckBox, newopt, painter) 

    def sizeHint (self, option, index): 
     return 18