如何知道触发了哪个 QMenu 的动作

Posted

技术标签:

【中文标题】如何知道触发了哪个 QMenu 的动作【英文标题】:how to know that which QMenu's action is triggered 【发布时间】:2018-01-29 15:51:58 【问题描述】:

我有一些 QAction,并在许多 QMenu 小部件中添加了相同的 QAction。 所有动作都连接到同一个插槽。我想知道触发了哪些 QMenu 操作。

【问题讨论】:

提供minimal reproducible example 您可以尝试插槽中的sender() 功能,但如果不了解您的应用程序,我不确定。 sender() 返回一个指向发送信号的对象的指针。并且信号是由 QAction 发送的,我如何知道触发了哪个 QMenu 操作。 如果同一个QAction绑定了同一个slot - 为什么你需要知道哪个被触发了?如果有原因,要么绑定不同的插槽,要么使用附加参数绑定插槽以进行标识。 (假设您使用新的 Qt5 风格的信号绑定)。 (@xander 由于QAction 是“可共享的”,我不确定sender() 是否足以区分。) connect(playlist_action, SIGNAL(triggered()), this, SLOT(LoadPlaylist()));现在我在两个 QMenu 中添加了“playlist_action”。现在当 playlist_action 被触发时如何区分 【参考方案1】:

三思而后行,得出以下结论:

如果同一个QAction被添加到多个菜单中,那么在槽中几乎没有机会区分哪个菜单项被触发了。

QAction 实例可以由多个菜单和工具栏共享。但在这种情况下,它是同一个实例(有多个父母)。出于同样的原因,使用附加参数进行区分的想法行不通。只有一个QAction 实例带有一个triggered 信号——没有区分的机会。

以下示例是我找到的最接近的示例 (testQActionShared.cc):

#include <QtWidgets>

void actionSlot(const char *text)

  qDebug() << "Action triggered:" << text;



int main(int argc, char** argv)

  qDebug() << "Version:" << QT_VERSION_STR;
  // main application
  QApplication app(argc, argv);
  QToolBar qToolbar;
  qToolbar.addAction(QString::fromUtf8("Action"),
    [](bool)  actionSlot("action1"); );
  qToolbar.addAction(QString::fromUtf8("Action"),
    [](bool)  actionSlot("action2"); );
  qToolbar.addAction(QString::fromUtf8("Action"),
    [](bool)  actionSlot("action3"); );
  qToolbar.show();
  // run application
  return app.exec();

testQActionShared.pro:

SOURCES = testQActionShared.cc

QT += widgets

cygwin 上以 bash 编译:

$ qmake-qt5 testQActionShared.pro

$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQActionShared.o testQActionShared.cc
g++  -o testQActionShared.exe testQActionShared.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 

$ ./testQActionShared 

Version: 5.9.2

应用程序如下所示:

我用鼠标点击了三个动作,得到如下输出:

Action triggered: action1
Action triggered: action2
Action triggered: action3

这实际上不是一个共享的QAction——它是三个具有相同标签文本和单独 lambdas 的操作。

lambda 已被用作适配器,以摆脱 QAction::triggered(bool) 的未使用的 bool 参数并改为绑定字符串。

注意:

我使用QToolBar 而不是QMenu 来保持样本更紧凑。不过原理是一样的。

【讨论】:

感谢您抽出宝贵的时间。我找到了我的答案here 我没有使用 QSignalMapper 的经验,因为我发现 lambdas 更方便。 (这可能是一个品味问题。)如果您可以提供一个带有(类似的小)示例的自我答案以进行演示,我很乐意看看它。 (学习新东西永远不会太晚。);-) 仔细查看链接的 Q/A,我意识到这些代码示例没有使用共享的 QAction - 它们使用具有相同插槽的不同 QActions(和我一样。 ) 我的程序中有两个QMenu,我在插槽中连接了两个不同的SLOTS connect(menu1, SIGNAL(triggered(QAction*)), this, SLOT(slot1(QAction*))); connect(menu2, SIGNAL(triggered(QAction*)), this, SLOT(slot2(QAction*))); 我在QAction 的帮助下区分QAction 并执行进一步操作。这对我很有用,因为我只有两个 QMenu 和许多 QAction 感谢您的想法,刚刚添加了 catch 'this' connect(copyUrlAction, &amp;QAction::triggered, this, [this](bool) OnCtxMenuAction(7); );

以上是关于如何知道触发了哪个 QMenu 的动作的主要内容,如果未能解决你的问题,请参考以下文章

强化学习——代理如何知道选择哪个动作?

如何知道在模式上按下关闭按钮时哪个按钮触发了模式

使用 QMenu 检查 QToolButton

超链接 MVC - 动作方法如何知道她在调用时位于哪个控制器中

Qt Connect 触发 QMenu 的 SIGNAL

如何将 QMenu 中的 QAction 转换为 QWidget?