5

我有 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)

我究竟做错了什么?

4

4 回答 4

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);
}
于 2010-11-12T15:01:42.167 回答
1

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

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

于 2020-01-25T08:09:51.180 回答
0

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

于 2013-12-12T09:31:27.603 回答
0

你实现了 removeRows 方法吗?

看看这里:

pyqt:试图了解 QAbstractDataModel 和 QTreeView 的插入行

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

希望这可以帮助 !

于 2010-11-11T12:29:47.807 回答