我想知道 QAction 是被鼠标左键还是右键点击

I want to know if QAction is clicked by left or right mouse button

我在 QMenu 中有一个 QAction。当 QActiontriggered() 我想知道是哪个按钮做的。

connect(YourAction, SIGNAL(triggered()), this, SLOT(actionclicked()));

void MainWindow::actionclicked(QMouseEvent *e)
{
    if (e->buttons() == Qt::RightButton) 
}

我不能做这样的事情,因为 triggered() 没有这样的论点。

triggered() 不能设计这个参数,因为它本身不一定是鼠标事件的结果:

This signal is emitted when an action is activated by the user; for example, when the user clicks a menu option, toolbar button, or presses an action's shortcut key combination, or when trigger() was called

如果需要QMouseEvent作为参数,则需要连接鼠标事件。事实上,当框架从菜单接收到鼠标事件时(但不仅仅是我在文档引用中强调的那样),Qt 本身会发出 triggered() 。所以看起来您需要在您的代码中做类似的事情并添加您自己的逻辑。

P.S。 This discussion 您可能会感兴趣

正如@mvidelgauz 所注意到的,QAction 是从可能触发操作的输入设备中抽象出来的。然而,如果在您的 GUI 中使用该操作,它有一个或多个关联的小部件:工具栏中的工具按钮、菜单栏中的条目等等。这些小部件就像任何其他小部件一样,因此它们接收可以使用 installEventFilter and eventFilter 过滤的事件。这两个方法继承自QObject,所以几乎所有的Qt都存在class。例如,让我们创建一个带有 QMainWindow 和 QAction 的应用程序,名为 actionTest。然后让我们通过覆盖 main window 的 eventFilter 方法,将 main window 本身变成 actionTest 的关联小部件的操作过滤器:

bool eventFilter(QObject *obj, QEvent *ev) {
    //Catch only mouse press events.
    if(ev->type() == QEvent::MouseButtonPress) {
        // Cast general event to mouse event.
        QMouseEvent *mev = static_cast<QMouseEvent*>(ev);
        // Show which button was clicked.
        if(mev->button() == Qt::LeftButton) {
            qDebug() << "Left button!";
        }
        if(mev->button() == Qt::RightButton) {
            qDebug() << "Right button!";
        }
    }
    // In this example we just showed the clicked button. Pass the event
    // for further processing to make QAction slots work.
    return QMainWindow::eventFilter(obj, ev);
}

然后我们需要为所有被监视的对象安装事件过滤器对象,在我们的例子中是小部件。让我们在主 window 构造函数中进行:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    for(auto wgtPtr : ui->actionTest->associatedWidgets()) {
        wgtPtr->installEventFilter(this);
    }
}

最后,为 triggered() 信号处理添加一个插槽:

void on_actionTest_triggered() {
    qDebug() << "Action triggered!";
}

现在如果您用鼠标左键单击操作菜单条目,它将打印

Left button!
Action triggered!

而对于鼠标右键,结果将是

Right button!
Action triggered!

请注意,小部件事件过滤始终在 triggered() 信号发射之前执行。

以上代码只是一个例子,MainWindow class 不是承载 eventFilter 方法的最佳位置。在实际代码中,您可以:

  1. QAction 小部件事件过滤创建专用 QObject 子class(es)。
  2. Subclass QAction 并覆盖它的 eventFilter 方法。在这种情况下,您可以将 QMouseEvent::button() 的结果保存在 QAction subclass 对象中,然后在 triggered() 信号处理程序中使用它。 Qt creator(至少到 v3.2.1)不允许你在它的表单设计器中 "promote" QActions 有一个小的不便,所以你需要在菜单中手动添加操作window 构造函数。
  3. Subclass QMenu, QToolBar, 等等,并使它们成为动作过滤器?我不知道它怎么能比以前的两个变体更好。

另见 documentation 关于 Qt 事件系统。

让我们澄清一下情况 2。假设从 QAction 继承的 class 称为 MyAction。为了使其工作,您需要安装 MyAction 个对象作为它们自己的过滤器(更具体地说,它们的小部件)。您需要在创建小部件后执行此操作,因此在 MyAction 构造函数中安装过滤器可能为时过早并导致崩溃。过滤器安装的更好位置是拥有 MyAction 对象的 class 的构造函数。通常它是一个小部件或 window class。所以只需添加

for(auto wgtPtr : ui->myActionObject->associatedWidgets()) {
    wgtPtr->installEventFilter(ui->myActionObject);
}
ui->setupUi(this) 调用后

到您的 window 构造函数。这段代码就像上面的例子,但是我们使用 ui->myActionObject 而不是 this 对象作为过滤器。