如何在Qt 4.4.1中检测应用程序级别的焦点获取?

3

我需要确定我的Qt 4.4.1应用程序何时接收到焦点。

我想出了两种可能的解决方案,但它们都不能完全满足我的需求。

在第一种可能的解决方案中,我将qApp的focusChanged()信号连接到一个SLOT上。在该槽中,我检查“旧”的指针。如果它是“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。显然我不希望这种情况发生。
同样地,如果用户在使用应用程序的打开和关闭对话框以及其他窗口等,我也不希望这个例程被激活。注意:我不确定在什么情况下会激活这个例程,因为我已经尝试过一些操作,但并不是所有的窗口和对话框都会激活,至少在示例代码中显示的窗口中会激活。
我只想在应用程序从外部聚焦到该应用程序时激活它,而不是当从其他对话框窗口聚焦到主窗口时激活它。
这是否可能?如何实现?
感谢您提供任何信息,因为这对我们的应用程序非常重要。
雷蒙德。
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 );
    ...
}

1

当您的对话框打开时,键盘事件不会发送到主窗口。在对话框关闭后,它们才会发送到主窗口,这是一种焦点切换。如果您想忽略焦点从应用程序中的另一个窗口切换的情况,则需要知道应用程序中任何窗口是否具有焦点。创建一个变量并在函数中添加一些逻辑。这需要一些小心,因为在主窗口获得焦点之前,对话框将失去焦点。


0
看Qt文档,似乎每次小部件获得焦点时都会创建焦点事件,因此您发布的示例代码由于您所述的原因而无法工作。
我猜测QApplication::focusedChanged不按您想要的方式工作,因为某些小部件不接受键盘事件,因此即使在同一应用程序中更改焦点,它们也返回null作为“旧”小部件。
我想知道是否可以使用QApplication::activeWindow()来做任何事情。

返回具有键盘输入焦点的应用程序顶级窗口,如果没有应用程序窗口具有焦点,则返回0。请注意,即使没有focusWidget(),也可能存在activeWindow(),例如,如果该窗口中没有小部件接受键事件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接