【问题标题】:Row, deleted from model, stays in view, what am I doing wrong?从模型中删除的行仍在视图中,我做错了什么?
【发布时间】:2011-05-07 23:50:36
【问题描述】:

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

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)

我做错了什么?

【问题讨论】:

    标签: qt pyqt qtableview


    【解决方案1】:

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

    我为解决问题的方式感到羞耻,但这是我丑陋的 hack:

    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)
    

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

    第二个解决方案,没那么讨厌:

    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);
    }
    

    【讨论】:

      【解决方案2】:

      我最近遇到了同样的问题,并为自己找到了另一种解决方案。 如果你只有一个 QTableView 连接到这个模型,你可以在 QSqlTableModel.deleteRow() 之后使用 QTableView.setRowHidden() 方法。工作正常。

      (我更愿意删除自定义绘制委托中的文本......但我找不到合适的标志来区分非提交的行。)

      【讨论】:

        【解决方案3】:

        你实现了 removeRows 方法吗?

        看看这里:

        pyqt: Trying to understand insertrows for QAbstractDataModel and QTreeView

        我想缺少的只是一个 emitDataChanged ,它告诉视图发生了一些变化!没有它,视图就无法知道它是否必须刷新自己!

        希望这会有所帮助!

        【讨论】:

        • beginRemoveRowsendRemoveRows
        • QSqlRelationalTableModel 已经有删除行,用 beginRemoveRows 和 endRemoveRows 正确实现。
        • 我调查过,这种讨厌的行为是设计使然。行在提交时从模型中删除,并且没有视图知道必须绘制哪些行,哪些不需要。当从模型中删除的行是“!”时,唯一要做的事情header.model().headerData(index, vert).text() 中的标记,这很恶心。我шьздуьутеув的解决方法,稍后会在这里发布。
        【解决方案4】:

        如果你想从模型中删除选定的行,你只需要调用:model->removeRow(row); 这里的行是您要删除的行号。 这对我来说很好。

        【讨论】:

        • SqTableModel 的RemoveRow 方法不会立即删除它。它标记要删除的行,然后在 commit() 上将其删除。我试图改变这种行为。
        猜你喜欢
        • 2014-05-09
        • 2023-01-01
        • 1970-01-01
        • 2012-09-27
        • 1970-01-01
        • 2019-04-20
        • 2020-01-29
        • 2022-01-22
        • 2013-10-20
        相关资源
        最近更新 更多