C++ 数据更改时自动刷新 QTableView
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12893904/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Automatically refreshing a QTableView when data changed
提问by piwi
I have written a custom data model to be displayed with several QTableViews.
我编写了一个自定义数据模型,用于显示多个 QTableView。
Technically, everything works fine: my views show the changes made from my model. My data model is editable, and the setData()
method does emit the dataChanged()
signal and returns true
on successful edition.
从技术上讲,一切正常:我的视图显示了对我的模型所做的更改。我的数据模型是可编辑的,并且该setData()
方法确实会发出dataChanged()
信号并true
在成功编辑时返回。
However, my problem is that I have to move my mouse over a QTableView
for it to show the actual change, while I would like all views to show the changes when they were made, without needing to interact with the views in order for them to be updated.
但是,我的问题是我必须将鼠标移到 aQTableView
上才能显示实际更改,而我希望所有视图在进行更改时都显示更改,而无需与视图交互以使它们成为更新。
Any idea? Thanks,
任何的想法?谢谢,
It may be relevant to mention that I do not use the default Qt::EditRole
role to edit data, but rather a custom enum value (named ActiveRole
).
值得一提的是,我不使用默认Qt::EditRole
角色来编辑数据,而是使用自定义枚举值(名为ActiveRole
)。
Here is what I am seeking: my data model contains properties on how to display data, used to generate style sheets that are fed to the viewS.
这是我所寻求的:我的数据模型包含有关如何显示数据的属性,用于生成馈送到视图的样式表。
Thus, when altering the model, for each view, all its items are impacted, which is why the dataChanged()
signal is sent with indices covering all cells.
因此,当改变模型时,对于每个视图,它的所有项目都会受到影响,这就是为什么dataChanged()
信号发送时带有覆盖所有单元格的索引。
I also tried to emit layoutChanged()
, but it does not seem to change the behavior in my case.
我也尝试发出layoutChanged()
,但它似乎并没有改变我的行为。
Here is an excerpt of the setData()
method:
以下是该setData()
方法的摘录:
bool DataModel::setData(QModelIndex const& idx, QVariant const& value, int role)
{
if (ActiveRole == role)
{
// Update data...
QModelIndex topLeft = index(0, 0);
QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1);
emit dataChanged(topLeft, bottomRight);
emit layoutChanged();
return true;
}
return false;
}
Here is a sample of the data()
method:
这是该data()
方法的示例:
QVariant DataModel::data(QModelIndex const& idx, int role) const
{
if (ActiveRole == role)
{
boost::uuids::uuid id;
return qVariantFromValue(id);
}
return QVariant();
}
And flags()
does indicate an editable model:
并且flags()
确实表明了一个可编辑的模型:
Qt::ItemFlags DataModel::flags(QModelIndex const& idx) const
{
if (false == idx.isValid())
{
return Qt::ItemIsEditable;
}
return QAbstractTableModel::flags(idx) | Qt::ItemIsEditable;
}
I have a custom delegate, which relies heavily on this SO threadfor overriding the paint
and the sizeHint
methods in order to draw a QTextDocument
. Also, it provides the content of the ActiveRole
to the editor in setEditorData
, and calls DataMode::setData
in setModelData
:
我有一个自定义委托,它在很大程度上依赖于这个SO 线程来覆盖paint
和sizeHint
方法以绘制QTextDocument
. 此外,它提供的内容ActiveRole
在编辑器setEditorData
,并呼吁DataMode::setData
在setModelData
:
void DataModelDelegate::setEditorData(QWidget* editor, QModelIndex const& idx) const
{
auto active = qVariantValue<boost::uuids::uuid>(idx.data(ActiveRole));
static_cast<DataModelEditor*>(editor)->setActive(active);
}
void DataModelDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, QModelIndex const& idx) const
{
auto active = static_cast<DataModelEditor*>(editor)->getActive();
model->setData(idx, qVariantFromValue(active), ActiveRole);
}
In the createEditor()
, I plug a signal from the editor to a slot of my delegate for committing data:
在 中createEditor()
,我将来自编辑器的信号插入到我的委托的插槽中以提交数据:
QWidget* DataModelDelegate::createEditor(QWidget* parent, QStyleOptionViewItem const& option, QModelIndex const& idx) const
{
auto editor = new DataModelEditor(parent);
connect(editor, SIGNAL(activeItem()), this, SLOT(commitEditorData()));
return editor;
}
When clicking on an item, the editor triggers the activeItem
signal; the connected slot commitEditorData
in turn raises the commitData
signal with the editor in argument.
当点击一个项目时,编辑器触发activeItem
信号;连接的插槽commitEditorData
依次commitData
用参数中的编辑器引发信号。
So all my views use these custom delegate, editor, and data model. The view that I am interacting with does show the change immediately, but the other views need to have the mouse hovering over them to show changes as well.
所以我所有的视图都使用这些自定义委托、编辑器和数据模型。我正在与之交互的视图确实会立即显示更改,但其他视图也需要将鼠标悬停在它们上方以显示更改。
采纳答案by piwi
I actually found the problem, which was that my other view was not properly notified of the data changes: my views each showed different portions of my data, so the other views needed to be notified of the dataChanged()
, but for their own, proper, indices.
我实际上发现了问题,即我的另一个视图没有正确通知数据更改:我的每个视图都显示了我数据的不同部分,因此其他视图需要通知dataChanged()
,但对于它们自己的正确索引.
On a side note, I also had the problem of updating my views while my Qt application was not the active window in my window manager. The solution was to call repaint()
on the main window.
附带说明一下,当我的 Qt 应用程序不是窗口管理器中的活动窗口时,我也遇到了更新视图的问题。解决方案是调用repaint()
主窗口。
回答by piwi
I have met the same problem, and let me add a detailed explanation to the piwi's answers. If you change the data,and what to update the single or several columns(or rows,depending on your requirement), you should emit a set of index for topleft to bottomright.For example,if you have a table like below:
我也遇到了同样的问题,让我在piwi的答案中添加详细说明。如果您更改数据,以及更新单列或多列(或行,取决于您的要求)的内容,您应该发出一组从左上角到右下角的索引。例如,如果您有一个如下表:
and, now you have changed some data, and want to update the cell row 1, column 1-2, then you should emit signal dataChange
并且,现在您已经更改了一些数据,并且想要更新单元格第 1 行、第 1-2 列,那么您应该发出信号dataChange
emit datachange(index(1,1),index(1,2));
回答by Pavel Zdenek
Are you calling the setData()
? Is the dataChanged()
signal really emitted? Connect some debug logging slot to it. I dare to speculate that this is very similar problem to yours:
你在打电话setData()
吗?在dataChanged()
信号发射真的?将一些调试日志插槽连接到它。我敢推测这与您的问题非常相似: