在Qt信号中,如何取消事件(类似于CancelEvent)?

5
我通常使用 .net 框架,最近有机会参与一个使用 C++/Qt 的项目。在这个背景下,我想要实现以下功能:(为了简化问题,假设我有一个 ListView 和一个 Textbox/Textedit)
  • 如果我选择 ListView 中的一个项目 -> 在 textedit 中显示相应的文本 (已完成)
  • 如果我编辑文本并点击列表中的另一个项目 -> 显示一个对话框询问是否保存或取消更改 (已完成)。文本编辑器从列表中接收到一个信号,告诉它所选的项目已经更改。
  • 如果用户按保存 -> 将其保存并刷新列表中的项目,新的项目被选中 (已完成)
  • 如果用户按取消 -> 不要选择用户点击的其他项目 (这就是我的问题所在)

基本上我看到两种解决方案(可能还有更多):

  • 从textedit发送一个信号回到列表,告诉列表恢复先前的选择。我个人不太喜欢这个解决方案,因为它们之间的耦合更强了(列表向textedit发送信号,现在也是反过来)。而且,这种“强制”选择恢复可能会再次触发后续信号,这些信号必须再次被阻止...
  • 一个更好的解决方案(我认为)是在信号中有一些否决机制。我可以想象列表发送两个信号:
    • 让我们称第一个为aboutToChangeSelection(proposedSelection,vetoObj)
    • 在操作完成后另一个:changedSelection(newSelection)

第一个信号将被发送到textedit,然后textedit最终将利用其否决权。之后,同样的信号将被发送到列表本身,根据否决权执行操作,并在实际更改选择时发送第二个信号。

在.NET世界中,有这样一种机制,借助于CancelEventArgs的帮助。我知道.NET事件和Qt信号有着非常不同的工作原理,但是是否有任何Qt等效方法来实现相同的效果呢?
非常感谢您的帮助!
2个回答

1
如果您使用的是QListWidget而不是QListView,那么可以执行以下操作:
  • 监听QListWidget::itemPressed ( QListWidgetItem * item )信号,而不是说项目已更改的信号(例如,在我的示例中currentItemChanged ( QListWidgetItem * current, QListWidgetItem * previous )
  • 打开对话框的函数是连接到此信号的插槽。我认为它不需要修改。
  • 听取信号:currentItemChanged ( QListWidgetItem * current, QListWidgetItem * previous ),仅用于记住当前和最后一个项目。
  • 现在在您的情况下,当用户设置取消时,以编程方式切换回上一个项目。

现在有一个问题,哪个信号会先接收到?文档中没有指定,可以按任何顺序。如果用户在项目A上,并单击项目B,则您希望在处理itemPressed时,lastitem为A,当前项目为B。因此,您希望首先处理currentItemChanged。幸运的是,您可以使用Qt::DirectConnection处理currentItemChanged,并使用Qt::QueuedConnection处理itemPressed

替代方案:

您可以在列表小部件上使用event filter。该过滤器将执行您描述的处理步骤。如果用户点击接受,则将事件发送到列表视图。如果用户拒绝,则阻止该事件。我不确定,但可能不会在过滤器中处理事件,这将使此替代方案不可行。


谢谢你们两个的回答!@UmNyobe:你提出的解决方案更像是我想要的。然而,对于问题“Qt中是否有内置等效项”的答案似乎是“没有”。因此,我重新构建了架构,现在只使用普通信号。无论如何:感谢你们的帮助! - Philip Daubmeier

0

我不是100%确定,但你可以重写QCoreApplication::notify( QObject * receiver, QEvent * event ),尝试找到正确的事件并在其上调用ignore()。为了判断何时忽略,你可以添加一个新的QEvent子类,在其中嵌入目标元素指针,并使其充当否决事件 - 如果接收到它,则知道你将要忽略特定对象的下一个某种特定类型的事件。


他想要监听一个事件,询问用户采取行动,并根据用户的行动执行两个不同的操作。因此,忽略事件是没有用的。 - UmNyobe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接