2010-11-10 22 views
2

J'ai QTableView, rempli par QSqlRelationalTableModel. Les modifications doivent être validées ou annulées à l'appel du bouton. Lorsque je modifie une ligne, elle change d'état dans la vue lorsque la modification est terminée et valide avec succès les modifications apportées à la base de données lorsque submitAll() est appelée. Mais quand j'essaye de supprimer une ligne, elle reste visible. Voici la fente, connecté au bouton Supprimer:Ligne, supprimé du modèle, reste en vue, qu'est-ce que je fais mal?

def _removeSelectedStatuses(self): 
    ''' 
    Удаляет выбранные строки из таблицы 

    pre[self]: self._model is not None 
    ''' 
    model = self.ConservationStatusesTableView.selectionModel() 
    l = model.selectedRows() 
    if not len(l): return 

    rows = set([i.row() for i in l]) 
    rows = list(rows) 
    rows.sort() 
    first = rows[0] 
    count = len(rows) 
    self._model.removeRows(first, count) 

Qu'est-ce que je fais mal?

Répondre

1

J'ai étudié, que ce comportement méchant est de par sa conception. Les lignes sont supprimées du modèle lors de la validation, et aucune vue ne sait, quelles lignes doivent être dessinées et lesquelles ne le sont pas. La seule chose à faire lorsque les lignes retirées du modèle est '!' marqueur dans header.model(). headerData (index, vert) .text(). Et c'est dégueulasse.

J'ai honte la façon dont je résolu le problème, mais voici mon bidouille horrible:

from PyQt4 import QtGui 
from PyQt4 import QtSql 
from PyQt4 import QtCore 

class SqlTableView(QtGui.QTableView): 
    ''' 
    Представление, которое не показывает удалённые столбцы, 
    когда коммит ещё не прошёл 
    ''' 


    def __init__(self, parent = None): 
     ''' 
     Конструктор 
     ''' 
     QtGui.QTableView.__init__(self, parent) 

    def setModel(self, model): 
     ''' 
     Мы не можем соединиться с моделями, не являющимися QSqlTableModel 
     ''' 
     assert isinstance(model, QtSql.QSqlTableModel) 
     QtGui.QTableView.setModel(self, model) 

    def paintEvent(self, event): 
     ''' 
     Тут всё и происходит. Осторожно, может стошнить. 
     ''' 
     if self.model() is not None: 
      header = self.verticalHeader() 
      hm = header.model() 
      for i in range(hm.rowCount()): 
       if (hm.headerData(i, QtCore.Qt.Vertical).toPyObject() == '!' 
        and not header.isSectionHidden(i)): 
        header.hideSection(i) 
       elif (header.isSectionHidden(i) and 
        hm.headerData(i, QtCore.Qt.Vertical).toPyObject() != '!'): 
        header.showSection(i) 
     PyQt4.QtGui.QTableView.paintEvent(self, event) 

J'ai aussi ajouté à QtDesigner pour simplifier la conception d'interface.

Deuxième solution, pas si méchant:

class PSqlRelationalTableModel : public QSqlRelationalTableModel 
{ 
    Q_OBJECT 

public: 
    explicit PSqlRelationalTableModel(QObject *parent = 0, 
     QSqlDatabase db = QSqlDatabase()); 
    virtual ~PSqlRelationalTableModel(); 

    bool removeRows(int row, int count, 
     const QModelIndex &parent = QModelIndex()); 

public slots: 
    void revertRow(int row); 

signals: 
    void rowIsMarkedForDeletion(int index); 
    void rowDeletionMarkRemoved(int index); 

private: 
    QSet<unsigned int> rowsToDelete; 
}; 

////////////////////////////////////////////////////////////////// 
void PTableView::setModel(PSqlRelationalTableModel *model) 
{ 
    connect(model, SIGNAL(rowIsMarkedForDeletion(int)), 
     this, SLOT(onRowMarkedForDeletion(int))); 
    connect(model, SIGNAL(rowDeletionMarkRemoved(int)), 
     this, SLOT(onRowDeletionMarkRemoved(int))); 
    QTableView::setModel(model); 
} 

void PTableView::onRowMarkedForDeletion(int index) 
{ 
    QHeaderView *hv = verticalHeader(); 
    hv->hideSection(index); 
} 

void PTableView::onRowDeletionMarkRemoved(int index) 
{ 
    QHeaderView *hv = verticalHeader(); 
    hv->showSection(index); 
} 
0

Avez-vous implémenté la méthode removeRows?

Jetez un oeil ici:

pyqt: Trying to understand insertrows for QAbstractDataModel and QTreeView

Je suppose que ce qui manque est tout simplement un emitDataChanged qui indique à l'idée que quelque chose a changé! Sans cela, la vue ne peut pas savoir si elle doit se rafraîchir!

Espérons que cela aide!

+0

Ou 'beginRemoveRows' et' endRemoveRows'. – andref

+0

QSqlRelationalTableModel possède déjà des lignes de suppression, implémentées correctement avec beginRemoveRows et endRemoveRows. –

+0

J'ai étudié, que ce comportement méchant est par conception. Les lignes sont supprimées du modèle lors de la validation, et aucune vue ne sait, quelles lignes doivent être dessinées et lesquelles ne le sont pas. La seule chose à faire lorsque les lignes retirées du modèle est '!' marqueur dans header.model(). headerData (index, vert) .text() Et c'est dégoûtant. Je шьздуьутеув la solution de contournement et l'afficherai ici plus tard. –

0

Si vous souhaitez supprimer la ligne sélectionnée à partir d'un modèle que vous avez juste besoin d'appeler: Model-> removeRow (ligne); Ici, ligne correspond au numéro de ligne que vous souhaitez supprimer. Cela fonctionne très bien pour moi.

+0

La méthode RemoveRow pour SqTableModel ne le supprime pas immédiatement. Il marque une ligne pour la suppression, puis supprime-le sur commit(). J'ai essayé de changer ce comportement. –