Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: moesefОтветов: 2

У меня есть 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? Может быть, способ бросить фиктивный сигнал или что-то в этом роде?

focusqtevent-handlingsystem-tray

Ответы

Ответ 1 · рейтинг 1 · Jedao

Ну, мне нужно было сделать то же самое, и я не мог понять, как сделать это чисто с чистым кодом 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;
    }
}

Ответ 2 · trompa

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

Вы позволяете 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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы