Я хочу знать, нажата ли QAction левой или правой кнопкой мыши

у меня есть QAction на QMenu. Когда QAction is triggered() Я хотел бы знать, какая кнопка это сделал.

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

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

Я не могу сделать что-то подобное, потому что triggered() нет такого аргумента.

2 ответов


как заметил @mvidelgauz,QAction абстрагируется от устройств ввода, которые могут инициировать действие. Тем не менее, если действие используется в вашем GUI, оно имеет один или несколько связанных виджетов: кнопки инструментов на панели инструментов, записи в строке меню и так далее. Эти виджеты действуют как любые другие виджеты, поэтому они получают события, которые могут быть отфильтрованы с использованием installEventFilter и eventFilter. Эти два метода наследуются от QObject, поэтому они присутствуют практически в любом классе Qt. Например, давайте создадим приложение с QMainWindow и QAction под названием actionTest. Тогда давайте превратим само главное окно в фильтр действий для actionTestсвязанные виджеты путем переопределения главного окна eventFilter способ:

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);
}

Затем нам нужно установить объект фильтра событий для всех наблюдаемых объектов, которые являются виджетами в нашем случае. Давайте сделаем это в конструкторе главного окна:

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 класс не лучшее место для размещения eventFilter метод. В реальном коде вы можете либо:

  1. создать посвящается QObject подкласс(ы)QAction фильтрация событий виджетов.
  2. подкласс QAction и переопределить это eventFilter метод. В этом случае вы можете просто сохранить результат QMouseEvent::button() на QAction объект подкласса и позже использовать его в triggered() обработчик сигнала. Существует небольшое неудобство, что Qt creator (по крайней мере, до v3.2.1) не позволяет вам "продвигать" QActions в дизайнере форм, поэтому вам нужно будет добавить действия в меню вручную в окне конструктор.
  3. подкласс QMenu, QToolBar, etc.., и сделать их фильтрами действий? Я не знаю, как это может быть лучше, чем два предыдущих варианта.

см. также документация о системе событий Qt.

давайте проясним случай 2. Предположим, что класс унаследован от QAction называется MyAction. Чтобы заставить его работать, вам нужно установить MyAction объекты в качестве фильтров для себя (их виджеты, чтобы быть более конкретными). Вам нужно сделать это после того, как виджеты были созданы, поэтому установка фильтра в MyAction конструктор может быть преждевременным и привести к сбоям. Лучшим местом для установки фильтра является конструктор класса, которому принадлежит


triggered() не может быть, этот аргумент, поскольку он сам по себе не обязательно является результатом события мыши:

этот сигнал испускается, когда действие активируется пользователем; например, когда пользователь нажимает кнопку меню, Панель инструментов,или нажимает комбинацию клавиш быстрого доступа действия, или когда trigger () был вызван

вам нужно подключиться к событиям мыши, Если вам нужно QMouseEvent в качестве параметра. На самом деле Qt сам излучает triggered() когда (но не только, как я выделил в цитате doc) framework получает событие мыши из меню. Таким образом, похоже, вам нужно будет сделать аналогичную вещь в своем коде и добавить свою собственную логику.

П. С. эта дискуссия может быть интересно для вас