Как мне определить уровень приложения Focus-In в Qt 4.4.1? - PullRequest
3 голосов
/ 15 сентября 2008

Мне нужно определить, когда мое приложение Qt 4.4.1 получает фокус.

Я предложил 2 возможных решения, но оба они работают не так, как хотелось бы.

В первом возможном решении я подключаю сигнал focusChanged () от qApp к слоту. В слоте я проверяю «старый» указатель. Если оно равно «0», то я знаю, что мы переключились на это приложение, и я делаю то, что хочу. Похоже, что это наиболее надежный способ заставить приложение обнаружить фокус в двух представленных здесь решениях, но страдает от проблемы, описанной ниже.

Во втором возможном решении я отверг подпрограмму «focusInEvent ()» и делаю то, что хочу, если причина - «ActiveWindowFocusReason».

В обоих этих решениях код выполняется в те моменты, когда я этого не хочу.

Например, у меня есть этот код, который переопределяет подпрограмму focusInEvent ():

void
ApplicationWindow::focusInEvent( QFocusEvent* p_event )
{

  Qt::FocusReason reason = p_event->reason();

  if( reason == Qt::ActiveWindowFocusReason && 
      hasNewUpstreamData() )
  {
    switch( QMessageBox::warning( this, "New Upstream Data Found!",
                                  "New upstream data exists!\n"
                                  "Do you want to refresh this simulation?",
                                  "&Yes", "&No", 0, 0, 1 ) )
    { 
    case 0: // Yes
      refreshSimulation();
      break;
    case 1: // No
      break;
    }
  }
}

Когда это выполняется, появляется диалоговое окно QMessageBox. Однако, когда диалог закрывается нажатием «да» или «нет», эта функция немедленно вызывается снова, потому что я полагаю, что фокус переместился обратно в окно приложения в этой точке с ActiveWindowFocusReason. Очевидно, я не хочу, чтобы это произошло.

Аналогично, если пользователь использует диалоги открытия и закрытия приложений, окна и т. Д., Я не хочу, чтобы эта процедура активировалась. ПРИМЕЧАНИЕ: я не уверен в обстоятельствах, когда эта подпрограмма активирована, хотя, поскольку я немного попробовал, и это происходит не для всех окон и диалогов, хотя это происходит по крайней мере для того, что показано в примере кода .

Я хочу, чтобы он активировался только в том случае, если приложение сфокусировано снаружи этого приложения, а не в том случае, когда основное окно сфокусировано из других диалоговых окон.

Возможно ли это? Как это можно сделать?

Спасибо за любую информацию, так как это очень важно для нашего приложения.

Raymond.

Ответы [ 3 ]

7 голосов
/ 11 декабря 2008

Я думаю, вам нужно отследить событие QEvent :: ApplicationActivate .

Вы можете установить фильтр событий на свой экземпляр QApplication и затем искать его.

bool
ApplicationWindow::eventFilter( QObject * watched, QEvent * event )
{
    if ( watched != qApp )
        goto finished;

    if ( event->type() != QEvent::ApplicationActivate )
        goto finished;

    // Invariant: we are now looking at an application activate event for
    //            the application object
    if ( !hasNewUpstreamData() )
        goto finished;

    QMessageBox::StandardButton response =
            QMessageBox::warning( this, "New Upstream Data Found!",
                                  "New upstream data exists!\n"
                                  "Do you want to refresh this simulation?",
                                  QMessageBox::Yes | QMessageBox::No) );

    if ( response == QMessageBox::Yes )
      refreshSimulation();

finished:
    return <The-Superclass-here>::eventFilter( watched, event );
}

ApplicationWindow::ApplicationWindow(...)
{
    if (qApp)
        qApp->installEventFilter( this );
    ...
}
1 голос
/ 06 октября 2008

Когда ваш диалог открыт, события клавиатуры не переходят в главное окно. После того, как диалог закрыт, они делают. Это изменение фокуса. Если вы хотите игнорировать случай, когда фокус переключился из другого окна в вашем приложении, то вам нужно знать, имеет ли фокус любое окно в вашем приложении. Создайте переменную и добавьте немного больше логики в вашу функцию. Это потребует некоторой осторожности, так как диалоговое окно потеряет фокус непосредственно перед тем, как основное окно получит фокус.

0 голосов
/ 15 сентября 2008

Глядя на документы Qt, кажется, что события фокуса создаются каждый раз, когда виджет получает фокус, поэтому отправленный вами пример кода не будет работать по указанным вами причинам.

Я предполагаю, что QApplication :: focusChanged работает не так, как вы хотите, потому что некоторые виджеты не принимают события клавиатуры, а также возвращают ноль в качестве "старого" виджета даже при изменении фокуса в одном приложении.

Мне интересно, можете ли вы что-нибудь сделать с QApplication :: activeWindow ()

Возвращает окно верхнего уровня приложения, которое имеет фокус ввода с клавиатуры, или 0, если ни у какого окна приложения нет фокуса. Обратите внимание, что может быть activeWindow (), даже если нету focusWidget (), например, если ни один виджет в этом окне не принимает ключевые события.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...