3

Qt 4.4.1 アプリケーションがいつフォーカスを受け取るかを判断する必要があります。

私は2つの可能な解決策を考え出しましたが、どちらも希望どおりに機能しません。

最初の可能な解決策では、qApp からの focusChanged() シグナルを SLOT に接続します。スロットで、「古い」ポインターを確認します。'0' の場合、このアプリケーションに切り替えたことがわかり、やりたいことを実行します。これは、ここで紹介する 2 つのソリューションの中で、アプリケーションにフォーカスを検出させる最も信頼できる方法のようですが、以下に説明する問題があります。

考えられる 2 番目の解決策では、「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 を使用してその時点でフォーカスがアプリケーション ウィンドウに戻ったと思われるためです。明らかに、私はこれが起こることを望んでいません。

同様に、ユーザーがダイアログやウィンドウなどを開いたり閉じたりするアプリケーションを使用している場合、このルーチンをアクティブにしたくありません。注:少し試してみたので、このルーチンがアクティブになる状況はわかりません。すべてのウィンドウとダイアログで発生するわけではありませんが、少なくともサンプルコードに示されているものでは発生します。 .

メインウィンドウが他のダイアログウィンドウからフォーカスされたときではなく、アプリケーションがこのアプリケーションの外部からフォーカスされた場合にのみアクティブにしたい。

これは可能ですか?これはどのように行うことができますか?

これは私たちのアプリケーションにとって非常に重要なので、情報をありがとう。

レイモンド。

4

3 に答える 3

7

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 );
    ...
}
于 2008-12-11T02:04:43.493 に答える
1

ダイアログが開いているとき、キーボード イベントはメイン ウィンドウに移動しません。ダイアログが閉じられた後、それらは閉じます。それはフォーカスの変更です。アプリケーション内の別のウィンドウからフォーカスが切り替わった場合を無視したい場合は、アプリケーション内のいずれかのウィンドウがいつフォーカスを持つかを知る必要があります。変数を作成し、関数にもう少しロジックを追加します。メインウィンドウがフォーカスを得る直前にダイアログがフォーカスを失うため、これには注意が必要です。

于 2008-10-06T09:33:51.677 に答える
0

Qt ドキュメントを見ると、ウィジェットがフォーカスを取得するたびにフォーカス イベントが作成されるように見えるため、投稿したサンプル コードは、あなたが述べた理由で機能しません。

一部のウィジェットはキーボードイベントを受け入れないため、同じアプリ内でフォーカスを変更しても「古い」ウィジェットとして null を返すため、QApplication::focusedChanged は希望どおりに機能しないと思います。

QApplication::activeWindow() で何かできるかどうか疑問に思っています

キーボード入力フォーカスがあるアプリケーションの最上位ウィンドウを返します。フォーカスがあるアプリケーション ウィンドウがない場合は 0 を返します。focusWidget() がない場合でも、activeWindow() が存在する可能性があることに注意してください。たとえば、そのウィンドウ内のウィジェットがキー イベントを受け入れない場合などです。

于 2008-09-15T13:23:21.627 に答える