如何在Qt 4.4.1中检测应用程序级别的重点关注?
我需要确定Qt 4.4.1应用程序何时获得关注。
我想出了2种可能的解决方案,但是它们都不能完全按照我的意愿工作。
在第一个可能的解决方案中,我将来自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更改回应用程序窗口。显然,我不希望这种情况发生。
同样,如果用户正在使用应用程序打开和关闭对话框以及窗口等,我也不想激活此例程。注意:尽管我已经尝试了一点,但我不确定在激活此例程时的情况,尽管并非至少在示例代码中所示,但并非所有窗口和对话框都启用了该例程。
我只希望它在应用程序从该应用程序外部聚焦时激活,而不是在主窗口从其他对话框窗口聚焦时激活。
这可能吗?如何才能做到这一点?
感谢我们提供任何信息,因为这对于我们的应用程序非常重要。
雷蒙德
解决方案
回答
查看Qt文档,似乎每次小部件获得焦点时都会创建焦点事件,因此,由于我们陈述的原因,我们发布的示例代码将不起作用。
我猜想QApplication :: focusedChanged不能按我们想要的方式工作,因为某些小部件不接受键盘事件,因此即使在同一应用程序中更改焦点时也返回null作为"旧"小部件。
我想知道我们是否可以使用QApplication :: activeWindow()做任何事情
Returns the application top-level window that has the keyboard input focus, or 0 if no application window has the focus. Note that there might be an activeWindow() even if there is no focusWidget(), for example if no widget in that window accepts key events.
回答
打开对话框时,键盘事件不会进入主窗口。对话框关闭后,他们会这样做。这是重点变化。如果要忽略焦点从应用程序的另一个窗口切换到其他情况的情况,则需要知道应用程序中的任何窗口何时具有焦点。创建一个变量,并向函数添加更多逻辑。这将需要一些注意,因为对话框将在主窗口获得焦点之前失去焦点。
回答
我认为我们需要跟踪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 ); ... }