【问题标题】:QTreeView: how to abort selection changeQTreeView:如何中止选择更改
【发布时间】:2018-05-07 16:13:25
【问题描述】:

我的小部件中有一个QTreeView。在视图中选择一个项目时,我有 一个信号处理程序,用于更新详细信息窗口中的一系列信息小部件 关于所选项目。然后,用户可以编辑项目详细信息并提交 变回模型。

如果此选择更改时详细信息视图中的数据已被编辑 发生时,我会在替换数据之前向用户显示一个确认对话框 选择新项目时。如果用户取消,我想设置选择 树恢复到原来的样子。

我的插槽是这样连接的:

auto selection_model = treeview->selectionModel();
connect(
    selection_model, &QItemSelectionModel::currentChanged,
    this, &Editor::on_tree_selection_changed
)

在我的插槽中,代码结构如下:

void on_tree_selection_changed(QModelIndex const& index, QModelIndex const& previous)
{
    if(not confirm_editor_discard()) 
    { 
        // user does not want to override current edits
        log.trace("cancel item selection change");
        using SF = QItemSelectionModel::SelectionFlags;
        auto sm = treeview->selectionModel();
        sm->setCurrentIndex(previous, SF::SelectCurrent | SF::Rows);
    }
    else
    {
        // user wants to discard, so update the details view.
        log.trace("discard pending edits");
        set_details_from_model(index);
    }
}

但是,将当前索引设置回之前好像并没有 影响 TreeView;它仍然将新选择的项目显示为选中,并且 界面变得不连贯,因为详细信息中显示的项目是 不是树中选择的那个。

预期的行为是重新选择先前选择的项目,就好像没有 完全做出了新的选择。

【问题讨论】:

    标签: c++ qt qtreeview


    【解决方案1】:

    显然QTreeView 在调用currentChanged 插槽时忽略了选择模型的任何更新。

    这里的解决方案是将插槽称为QueuedConnection,因此connect 行将如下所示:

    connect(
        selection_model, &QItemSelectionModel::currentChanged,
        this, &Editor::on_tree_selection_changed,
        Qt::QueuedConnection // <-- connection must be queued. 
    )
    

    这将确保选择模型的选择更改不会直接发生在插槽调用中。

    【讨论】:

    • 它不能做很多其他事情:毕竟,你的插槽代码正在运行。但真正发生的是你被编写伪同步代码咬了。对话处理程序属于一个插槽!如果你这样做了,你就永远不会遇到这个问题。
    • 你能运行一个非同步的模态对话框吗?
    • 是的,你可以。模态只是 UI 的一种特殊状态,它不会改变它的异步行为。像运行伪同步代码这样的特殊技巧只是把问题扫到了地毯下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多