【发布时间】:2018-02-05 12:23:00
【问题描述】:
我有两个单独的线程。 第一个线程用于 GUI,第二个线程用于应用程序数据。
最初,我想使用 QUndoStack 和 QUndoView。
但是有一个问题——这个视图直接与堆栈一起工作:
在这种情况下,我得到了竞争条件。
为了解决这个问题,我使用 QListView 和 QAbstractListModel 编写了自定义 myUndoView。 现在我的所有插槽都使用排队连接,并且我将“真实”撤消堆栈的轻量级副本存储在自定义视图模型中。 这是“真实”撤消堆栈元素的相同大小和相同顺序。 轻量级元素仅包含撤消命令和文本的类型。
现在我有另一个问题。这不怪我))
我有一个 QLineEdit,当我单击 Enter 键或失去焦点时,它会在值更改时发出信号。 该值又被发送到具有“真实”撤消堆栈的对象(应用程序模型)。它有效。
但是当我也与撤消视图交互时,这不起作用。 重复一遍,这不怪我。 QUndoView 具有相同的行为。
一步一步:
- QLineEdit 成为焦点。
- 改变值,仍然是焦点。
- 在撤消视图中单击鼠标。
哎呀.. 撤消视图中的 currentIndexChanged() 信号可以先发送, 或者可以先发送来自 QLineEdit 的信号。
它总是不同的..
如果首先发送来自 QLineEdit 的信号 - 它工作正常。 变化的历史没有丢失。
我想让输入/模糊和其他更改(不在历史视图中)始终首先调用。可能我可以使用 QTimer::singleShot() 来延迟发出撤消视图信号。但不是curentIndexChanged(),因为这个信号会随着用户交互以及撤消堆栈以编程方式更新时发出。我们无法确定谁进行了更改 - 用户或应用程序。
我尝试了什么?
拦截鼠标点击:
myUndoView::mousePressEvent(QMouseEvent *event)
{
event->ignore();
qDebug() << "catched!";
}
但有时它会丢失点击次数。 列表项的底部(字母下方)是一个将点击传递给该项目的区域。 这可能是一个 Qt 错误,在我的环境中发现:Debian、Mate、GTK+ Qt-style。
我想,我可以在列表上放置另一个透明小部件,并获取点击的坐标并使用它:
http://doc.qt.io/qt-5/qabstractitemview.html#indexAt
获取选定的索引。
还是我全都错了? 也许有更简单的方法?
如何做到正确?
【问题讨论】:
-
您是否尝试过此解决方案中所述的排队信号stackoverflow.com/questions/15051553/…
-
@MohammadKanan 我所有的插槽(在应用程序线程中)都有排队连接。来自 GUI 的所有信号都发送到应用程序线程事件循环。但是当行编辑被聚焦时,点击历史项目发生得非常快,并且可以在行编辑信号之前发送。而且我无法将连接更改为直接类型 - 它缺少线程优势,gui 有时会冻结。