我有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)
我做错了什么?
答案 0 :(得分:1)
我调查过,这种讨厌的行为是设计的。在提交时从模型中删除行,并且没有视图知道,必须绘制哪些行,哪些不是。从模型中删除行的唯一操作是'!' header.model()中的标记.headerData(index,vert).text()。而且令人作呕。
我对解决问题的方式感到羞耻,但这是我的丑陋黑客:
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);
}
答案 1 :(得分:1)
我最近遇到了同样的问题,并为自己找到了另一个解决方案。 如果只有一个QTableView连接到此模型,则可以在QSqlTableModel.deleteRow()之后使用QTableView.setRowHidden()方法。效果很好。
(我更喜欢在自定义绘画委托中删除文本...但是我找不到合适的标志来区分非指定行)。
答案 2 :(得分:0)
您是否实施了removeRows方法?
看看这里:
pyqt: Trying to understand insertrows for QAbstractDataModel and QTreeView
我想缺少的只是一个emitDataChanged,告诉视图发生了变化!没有它,视图无法知道它是否必须刷新自己!
希望这有帮助!
答案 3 :(得分:0)
如果您想从模型中删除所选行,您只需要调用:model-&gt; removeRow(row); 这里的行是您要删除的行号。 这对我来说很好。