简体   繁体   English

我想知道是否用鼠标左键或右键单击QAction

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

I have a QAction in QMenu . 我在QMenuQAction When QAction is triggered() I would like to know which button did it. triggered() QAction triggered()我想知道哪个按钮做了。

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

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

I can't do something like this because triggered() does not have such argument. 我不能做这样的事情,因为triggered()没有这样的参数。

As @mvidelgauz noticed, QAction is abstracted from input devices which may triggered the action. 正如@mvidelgauz注意到的那样, QAction是从输入设备中抽象出来的,这可能会触发操作。 Nevertheless, if the action is used in your GUI, it has one or more associated widgets: tool buttons in a toolbar, entries in menu bar and so on. 但是,如果在GUI中使用该操作,则它具有一个或多个关联的小部件:工具栏中的工具按钮,菜单栏中的条目等。 These widgets act like any other widgets, so they receive events which may be filtered with the use of installEventFilter and eventFilter . 这些小部件的行为与任何其他小部件相同,因此它们接收可以使用installEventFiltereventFilter过滤的事件。 These two methods are inherited from QObject , so they are present in almost any Qt class. 这两个方法都是从QObject继承的,因此它们几乎存在于任何Qt类中。 For example, let's create an application with QMainWindow and QAction called actionTest . 例如,让我们用QMainWindow和QAction创建一个名为actionTest的应用程序。 Then let's turn the main window itself into an action filter for actionTest 's associated widgets by overriding main window's eventFilter method: 然后让我们通过覆盖主窗口的eventFilter方法将主窗口本身转换为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);
}

Then we need to install event filter object for all watched objects, which are widgets in our case. 然后我们需要为所有被监视对象安装事件过滤器对象,在我们的例子中是小部件。 Let's do it in main window constructor: 让我们在主窗口构造函数中执行:

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

Finally, add a slot for triggered() signal handling: 最后,添加一个用于triggered()信号处理的插槽:

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

Now if you click the action menu entry with left mouse button, it will print 现在,如果用鼠标左键单击操作菜单项,它将打印出来

Left button!
Action triggered!

while for right mouse button the result will be 而对于鼠标右键,结果将是

Right button!
Action triggered!

Note that widget event filtering is always performed before triggered() signal emission. 请注意,小部件事件过滤始终在triggered()信号发射之前执行。

The above code is just an example, and MainWindow class is not the best place to host eventFilter method. 上面的代码只是一个例子, MainWindow类不是托管eventFilter方法的最佳位置。 In real code you may either: 在实际代码中,您可以:

  1. Create dedicated QObject subclass(es) for QAction widgets event filtering. QAction小部件事件过滤创建专用的QObject子类。
  2. Subclass QAction and override it's eventFilter method. 子类QAction并覆盖它的eventFilter方法。 In this case you may just save the result of QMouseEvent::button() in the QAction subclass object and later use it in triggered() signal handler. 在这种情况下,您可以将QMouseEvent::button()的结果保存在QAction子类对象中,然后在triggered()信号处理程序中使用它。 There is a minor inconvenience that Qt creator (at least up to v3.2.1) does not allow you to "promote" QAction s in it's form designer, so you'll need to add actions to menus manually in window constructor. Qt创建者(至少高达v3.2.1)不允许您在其表单设计器中“提升” QAction ,因此您需要在窗口构造函数中手动向菜单添加操作,这是一个小小的不便。
  3. Subclass QMenu , QToolBar , etc.., and make them action filters? 子类QMenuQToolBar ,等,使他们的行动过滤器? I don't know how can it be better than two former variants. 我不知道它怎么能比两个以前的变种更好。

See also documentation about Qt event system. 另请参阅有关Qt事件系统的文档

Let's clarify case 2. Assume the class inherited from QAction is called MyAction . 让我们澄清一下案例2.假设从QAction继承的类叫做MyAction In order to make it work you need to install MyAction objects as filters for themselves (their widgets, to be more specific). 为了使其工作,您需要将MyAction对象安装为自己的过滤器(它们的小部件,更具体)。 You need to do it after widgets were created, so installing filter in MyAction constructor may be premature and lead to crashes. 您需要在创建窗口小部件后执行此操作,因此在MyAction构造函数中安装过滤器可能为时过早并导致崩溃。 Better place for filter installation is a constructor of a class which owns MyAction object. 过滤器安装的最佳位置是拥有MyAction对象的类的构造函数。 Typically it's a widget or window class. 通常它是一个小部件或窗口类。 So just add 所以只需添加

for(auto wgtPtr : ui->myActionObject->associatedWidgets()) {
    wgtPtr->installEventFilter(ui->myActionObject);
}

to your window constructor after ui->setupUi(this) call. ui->setupUi(this)调用之后到你的窗口构造函数。 This code is like in the above example, but we use ui->myActionObject instead of this object as filter. 此代码与上例中的代码类似,但我们使用ui->myActionObject而不是this对象作为过滤器。

triggered() cannot have this argument by design because it by itself is not necessarily result of a mouse event: 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 例如,当用户单击菜单选项,工具栏按钮或按下操作的快捷键组合时,或者在调用trigger()时

You need to connect to mouse events if you need QMouseEvent as parameter. 如果需要QMouseEvent作为参数,则需要连接到鼠标事件。 In fact Qt itself emits triggered() when (but not only as I highlighted in doc quote) framework receives mouse event from menu. 实际上Qt本身发出的是triggered() ,但是(不仅如我在doc引用中强调的那样)框架从菜单中接收鼠标事件。 So it looks like you'll need to do a similar thing in your code and add your own logic. 所以看起来你需要在代码中做类似的事情并添加自己的逻辑。

PS This discussion might be interesting for you PS 这个讨论对你来说可能很有意思

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM