QT: Контекстное меню на триггере

У меня есть QMenu, который находится в QSystemTrayIcon. Оба являются членами объекта QMainWindow.

Я хочу, чтобы QMenu QSystemTrayIcon действовал одинаково при щелчке правой кнопкой мыши (т. е. по причине QSystemTrayIcon::Context) и при одиночном щелчке левой кнопкой мыши (т. е. по причине QSystemTrayIcon::Trigger).

Поведение правой кнопки мыши по умолчанию действует так, как я этого хочу. Однако я не могу понять, как заставить левый щелчок действовать точно так же, как правый щелчок. Мои усилия до сих пор приводят меня к:

 void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
 {
     if(reason==QSystemTrayIcon::Trigger)  trayIcon->contextMenu()->popup(QCursor::pos());
 }

Однако меню не исчезает, когда оно теряет фокус, тогда как вызов контекстного меню с помощью правого щелчка заставляет его исчезнуть, когда фокус теряется.

Есть ли способ заставить Trigger действовать как Context? Может быть, способ бросить фиктивный сигнал или что-то в этом роде?


person moesef    schedule 08.05.2013    source источник


Ответы (2)


Ну, мне нужно было сделать то же самое, и я не мог понять, как сделать это чисто с чистым кодом Qt, поэтому вот небольшой хак только для Windows, который работает:

void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason)
    {
    case QSystemTrayIcon::Trigger:
    case QSystemTrayIcon::DoubleClick:
    case QSystemTrayIcon::MiddleClick:
        {
            POINT p;
            GetCursorPos(&p);
            HWND hwnd = WindowFromPoint(p);
            ScreenToClient(hwnd, &p);
            PostMessageA(hwnd, WM_RBUTTONDOWN, MK_RBUTTON, MAKELONG(p.x, p.y));
            PostMessageA(hwnd, WM_RBUTTONUP, 0, MAKELONG(p.x, p.y));
        }
        break;
    case QSystemTrayIcon::Context:
        show();
        setWindowState(windowState() & ~Qt::WindowMinimized | Qt::WindowActive);
        mTrayIcon->contextMenu()->popup(QCursor::pos());
        break;
    default:
        break;
    }
}
person Jedao    schedule 17.10.2013

Итак, если я правильно понял.

Вы позволяете Qt обрабатывать правую кнопку (вы не проверяете контекст в своем слоте), а затем меню исчезает, когда теряется фокус.

Но вы обрабатываете нажатия левой кнопки и не можете добиться такого же поведения. Правильно?

Я могу придумать, по крайней мере, два способа сделать это через eventFilter:

Это был бы способ сделать поддельное событие.

bool MainWindow::eventFilter(QObject *obj, QEvent *event){
if (event->type() == QEvent::MouseButtonPress) {
  QMouseEvent *mEvent = static_cast<QMouseEvent *>(event);
  if(mEvent->button() == Qt::LeftButton)
  {
    QMouseEvent my_event = new QMouseEvent ( mEvent->type(), 
        mEvent->pos(), Qt::Rightbutton , 
    mEvent->buttons(), mEvent->modifiers() );
     QCoreApplication::postEvent ( trayIcon, my_event );
    return true;
  }
} 
return QObject::eventFilter(obj, event);
}

Установить с помощью

trayIcon->installEventFilter(this);

из главного окна

Но, я думаю, это немного сложно.

Если вы создаете фильтр событий, вы можете следить за событием focusOut в меню.

bool MainWindow::eventFilter(QObject *obj, QEvent *event){

  QMouseEvent *mEvent = dynamic_cast<QMouseEvent *>(event);
  if(mEvent)
  {
  if(mEvent->type() == QEvent::Leave || mEvent->type() == QEvent::WindowDeactivate)
  {
    trayIcon->contextMenu()->close();
    return true;
  }
} 
return QObject::eventFilter(obj, event);
}

Обратите внимание, что я не пробовал. Но стоит попробовать.

Несколько полезных ссылок:

Как определить, что мое приложение потеряло фокус в Qt?< /а>

installEventFilter

postEvent

person trompa    schedule 08.05.2013
comment
ваше понимание правильное. И при чтении вашего примера кажется, что он должен работать, по какой-то причине eventFilter не запускается в моем коде. - person moesef; 09.05.2013
comment
Для второго метода установить в меню - person trompa; 09.05.2013
comment
И, возможно, также во втором методе это QEvent::MouseMove. немного изменю код - person trompa; 09.05.2013
comment
На самом деле я еще не пробовал второй способ. Мне понравился первый, потому что он заставляет левый щелчок мыши действовать точно так же, как правый щелчок (именно то, что я хочу), не проходя и не назначая каждое поведение самой левой мыши. Я попробую второй метод и посмотрю, что произойдет. - person moesef; 09.05.2013
comment
Обратите внимание, что я не пробовал код. Возможно, вам нужно сделать некоторые настройки, чтобы заставить его работать. Это было просто доказательство концепции - person trompa; 09.05.2013
comment
И, кстати, он должен попасть в eventFilter, даже если потом вы проверите не то событие - person trompa; 09.05.2013
comment
да. Я буду продолжать работать над этим. спасибо за помощь в начале работы. - person moesef; 09.05.2013