从模型中删除的行仍在视图中,我做错了什么?

Max*_*vko 5 qt pyqt qtableview

我有 QTableView,由 QSqlRelationalTableModel 填充。应该在点击按钮时提交或恢复更改。当我编辑某行时,它会在编辑完成时更改视图中的状态,并在调用 submitAll() 时成功提交对数据库的更改。但是当我尝试删除行时,它仍然在视图中。这是插槽,连接到删除按钮:

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)
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Max*_*vko 1

我调查发现,这种令人讨厌的行为是有意设计的。行在提交时从模型中删除,并且没有视图知道哪些行必须绘制,哪些行不需要绘制。从模型中删除行时唯一要做的事情是“!” header.model().headerData(index, vert).text() 中的标记。这很恶心。

\n\n

我对解决问题的方式感到羞愧,但这是我丑陋的黑客:

\n\n
from PyQt4 import QtGui\nfrom PyQt4 import QtSql\nfrom PyQt4 import QtCore\n\nclass SqlTableView(QtGui.QTableView):\n    '''\n    \xd0\x9f\xd1\x80\xd0\xb5\xd0\xb4\xd1\x81\xd1\x82\xd0\xb0\xd0\xb2\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5, \xd0\xba\xd0\xbe\xd1\x82\xd0\xbe\xd1\x80\xd0\xbe\xd0\xb5 \xd0\xbd\xd0\xb5 \xd0\xbf\xd0\xbe\xd0\xba\xd0\xb0\xd0\xb7\xd1\x8b\xd0\xb2\xd0\xb0\xd0\xb5\xd1\x82 \xd1\x83\xd0\xb4\xd0\xb0\xd0\xbb\xd1\x91\xd0\xbd\xd0\xbd\xd1\x8b\xd0\xb5 \xd1\x81\xd1\x82\xd0\xbe\xd0\xbb\xd0\xb1\xd1\x86\xd1\x8b, \n    \xd0\xba\xd0\xbe\xd0\xb3\xd0\xb4\xd0\xb0 \xd0\xba\xd0\xbe\xd0\xbc\xd0\xbc\xd0\xb8\xd1\x82 \xd0\xb5\xd1\x89\xd1\x91 \xd0\xbd\xd0\xb5 \xd0\xbf\xd1\x80\xd0\xbe\xd1\x88\xd1\x91\xd0\xbb\n    '''\n\n\n    def __init__(self, parent = None):\n        '''\n        \xd0\x9a\xd0\xbe\xd0\xbd\xd1\x81\xd1\x82\xd1\x80\xd1\x83\xd0\xba\xd1\x82\xd0\xbe\xd1\x80\n        '''\n        QtGui.QTableView.__init__(self, parent)\n\n    def setModel(self, model):\n        '''\n        \xd0\x9c\xd1\x8b \xd0\xbd\xd0\xb5 \xd0\xbc\xd0\xbe\xd0\xb6\xd0\xb5\xd0\xbc \xd1\x81\xd0\xbe\xd0\xb5\xd0\xb4\xd0\xb8\xd0\xbd\xd0\xb8\xd1\x82\xd1\x8c\xd1\x81\xd1\x8f \xd1\x81 \xd0\xbc\xd0\xbe\xd0\xb4\xd0\xb5\xd0\xbb\xd1\x8f\xd0\xbc\xd0\xb8, \xd0\xbd\xd0\xb5 \xd1\x8f\xd0\xb2\xd0\xbb\xd1\x8f\xd1\x8e\xd1\x89\xd0\xb8\xd0\xbc\xd0\xb8\xd1\x81\xd1\x8f QSqlTableModel\n        '''\n        assert isinstance(model, QtSql.QSqlTableModel)\n        QtGui.QTableView.setModel(self, model)\n\n    def paintEvent(self, event):\n        '''\n        \xd0\xa2\xd1\x83\xd1\x82 \xd0\xb2\xd1\x81\xd1\x91 \xd0\xb8 \xd0\xbf\xd1\x80\xd0\xbe\xd0\xb8\xd1\x81\xd1\x85\xd0\xbe\xd0\xb4\xd0\xb8\xd1\x82. \xd0\x9e\xd1\x81\xd1\x82\xd0\xbe\xd1\x80\xd0\xbe\xd0\xb6\xd0\xbd\xd0\xbe, \xd0\xbc\xd0\xbe\xd0\xb6\xd0\xb5\xd1\x82 \xd1\x81\xd1\x82\xd0\xbe\xd1\x88\xd0\xbd\xd0\xb8\xd1\x82\xd1\x8c.\n        '''\n        if self.model() is not None:\n            header = self.verticalHeader()\n            hm = header.model()\n            for i in range(hm.rowCount()):\n                if (hm.headerData(i, QtCore.Qt.Vertical).toPyObject() == '!' \n                    and not header.isSectionHidden(i)):\n                    header.hideSection(i)\n                elif (header.isSectionHidden(i) and \n                    hm.headerData(i, QtCore.Qt.Vertical).toPyObject() != '!'):\n                    header.showSection(i)\n        PyQt4.QtGui.QTableView.paintEvent(self, event)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还将它添加到 QtDesigner 中以简化界面设计。

\n\n

第二种解决方案,没那么令人讨厌:

\n\n
class PSqlRelationalTableModel : public QSqlRelationalTableModel\n{\n    Q_OBJECT\n\npublic:\n    explicit PSqlRelationalTableModel(QObject *parent = 0, \n        QSqlDatabase db = QSqlDatabase());\n    virtual ~PSqlRelationalTableModel();\n\n    bool removeRows(int row, int count, \n        const QModelIndex &parent = QModelIndex());\n\npublic slots:\n    void revertRow(int row);\n\nsignals:\n    void rowIsMarkedForDeletion(int index);\n    void rowDeletionMarkRemoved(int index);\n\nprivate:\n    QSet<unsigned int> rowsToDelete;\n};\n\n//////////////////////////////////////////////////////////////////\nvoid PTableView::setModel(PSqlRelationalTableModel *model)\n{\n    connect(model, SIGNAL(rowIsMarkedForDeletion(int)), \n        this, SLOT(onRowMarkedForDeletion(int)));\n    connect(model, SIGNAL(rowDeletionMarkRemoved(int)), \n        this, SLOT(onRowDeletionMarkRemoved(int)));\n    QTableView::setModel(model);\n}\n\nvoid PTableView::onRowMarkedForDeletion(int index)\n{\n    QHeaderView *hv = verticalHeader();\n    hv->hideSection(index);\n}\n\nvoid PTableView::onRowDeletionMarkRemoved(int index)\n{\n    QHeaderView *hv = verticalHeader();\n    hv->showSection(index);\n}\n
Run Code Online (Sandbox Code Playgroud)\n