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 更改回应用程序窗口。显然我不希望这种情况发生。

同样,如果用户正在使用应用程序打开和关闭对话框和窗口等,我不希望激活此例程。注意:我不确定激活此例程的情况,因为我已经尝试了一点,并且并非所有窗口和对话框都发生这种情况,但至少在示例代码中显示的情况下会发生这种情况.

我只希望它在应用程序从该应用程序外部聚焦时激活,而不是在主窗口从其他对话框窗口聚焦时激活。

这可能吗?如何才能做到这一点?

感谢您提供任何信息,因为这对我们的应用程序非常重要。

雷蒙德。

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 文档,似乎每次小部件获得焦点时都会创建焦点事件,因此由于您所述的原因,您发布的示例代码将不起作用。

我猜 QApplication::focusedChanged 不能按照您想要的方式工作,因为某些小部件不接受键盘事件,因此即使在同一个应用程序中更改焦点,也会返回 null 作为“旧”小部件。

我想知道你是否可以用 QApplication::activeWindow() 做任何事情

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

于 2008-09-15T13:23:21.627 回答