Как заметил @mvidelgauz, QAction
абстрагируется от устройств ввода, которые могут вызвать действие. Тем не менее, если действие используется в вашем графическом интерфейсе, оно имеет один или несколько связанных виджетов: кнопки инструментов на панели инструментов, записи в строке меню и т. Д. Эти виджеты действуют как любые другие виджеты, поэтому они получают события, которые могут быть отфильтрованы с использованием installEventFilter и eventFilter. Эти два метода наследуются от QObject
, поэтому они присутствуют почти в любом классе Qt. Например, создадим приложение с QMainWindow и QAction с именем actionTest
. Тогда давайте обратимся непосредственно главным окно в действии фильтр для ассоциированных виджетов actionTest
«s путем переопределения 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
.В реальном коде вы можете либо:
- Создание посвященный
QObject
подкласса (ов) для QAction
виджетов фильтрации событий.
- Подкласс
QAction
и переопределить его eventFilter
метод. В этом случае вы можете просто сохранить результат QMouseEvent::button()
в объекте подкласса QAction
, а затем использовать его в обработчике сигнала triggered()
. Существует незначительное неудобство, что создатель Qt (по крайней мере, до версии 3.2.1) не позволяет вам «продвигать» QAction
s в своем конструкторе форм, поэтому вам нужно будет добавлять действия в меню вручную в конструкторе окна.
- Подкласс
QMenu
, QToolBar
и т. Д., И сделать их фильтрами действий? Я не знаю, как это может быть лучше, чем два предыдущих варианта.
См. Также documentation о системе событий Qt.
Проясним случай 2. Предположим, что класс, унаследованный от QAction
, называется MyAction
. Чтобы сделать его работу, вам необходимо установить объекты MyAction
в качестве фильтров для себя (их виджеты, если быть более конкретными). Вам нужно сделать это после создания виджетов, поэтому установка фильтра в конструкторе MyAction
может быть преждевременной и привести к сбоям. Лучшим местом для установки фильтра является конструктор класса, которому принадлежит объект MyAction
. Обычно это класс виджета или окна. Так что просто добавить
for(auto wgtPtr : ui->myActionObject->associatedWidgets()) {
wgtPtr->installEventFilter(ui->myActionObject);
}
в окно конструктора после ui->setupUi(this)
вызова. Этот код похож на приведенный выше пример, но мы используем ui->myActionObject
вместо объекта в качестве фильтра.
Могу ли я создать eventFilter в классе, который я использую как QAction? У меня уже есть класс, который наследуется от QAction, и я использую его в своем приложении. Я переопределил метод eventFilter, но ничего не происходит. Должен ли я установить его где-нибудь? –
@ S.llous конечно вы можете. Я добавил разъяснение для случая 2 из моего ответа, который должен заставить ваш код работать. Попробуйте напечатать что-нибудь в 'qDebug()' из вашего метода 'eventFilter', чтобы убедиться, что он работает правильно. – Sergey
Будет ли это работать, когда я хочу использовать его на 'QSystemTrayIcon'? Мое приложение не имеет графического интерфейса, а только 'QActions' в' QSystemTrayIcon'. –