Mac OS X上的QWidget没有关注Qt 5.x.

时间:2013-07-01 11:34:03

标签: c++ macos qt qt5 qwidget

我有QSystemTrayIcon和QAction打开QWebView类型的新窗口。当窗口失去焦点并再次选择QAction时,窗口应重新获得焦点。它在Linux上运行,但在Mac OS X上没有。问题是,当我有另一个窗口打开并处于活动状态时,让我们说Google Chrome,当我在我试图打开的窗口上调用show()时,它总是在谷歌浏览器下打开,所以我没有看到它。聚焦也是如此,当我打开多个窗口时,我的QWebView可能是订单中的最后一个,当我点击QAction聚焦窗口时,它将始终位于谷歌浏览器窗口下。我的猜测是,当我点击QAction时,这是我应用程序流程的一部分,它将尝试打开/关注窗口,但在操作过程中,谷歌Chrome窗口会被安排并获得焦点,因为QSystemTrayIcon无法保持专注。因此,当窗口被打开/聚焦时,它不会从谷歌浏览器窃取焦点,因为操作系统不允许它,因此它将被放置在当前聚焦的窗口下。

这里我是如何创建/聚焦窗口的:

// ...
QPointer<QWebView> view;
// ...

void TrayIcon::webView() {
  if (!this->view) {
    this->view = new QWebView();
    this->view->load("http://example.com");
    this->view->show();
  } else {
    this->view->activateWindow();
    this->view->raise();
  }
}

我做错了什么或有没有已知的解决方法?

2 个答案:

答案 0 :(得分:6)

有点offtopic,但它可能对某些用户有用:

我的建议是创建平台依赖的代码来强制提升窗口。在Windows平台上存在同样的问题,所以我正在使用下一个hack:

    void Utils::forceForegroundWindow( WId winId )
    {
#ifdef Q_OS_WIN
        HWND hWnd = winId;

        if ( ::IsWindow( hWnd ) )
        {
            HWND hCurrWnd;
            int iMyTID;
            int iCurrTID;

            hCurrWnd = ::GetForegroundWindow();
            iMyTID   = ::GetCurrentThreadId();
            iCurrTID = ::GetWindowThreadProcessId( hCurrWnd, 0 );

            ::AttachThreadInput( iMyTID, iCurrTID, TRUE );

            ::ShowWindow( hWnd, SW_SHOWNORMAL );
            ::SetForegroundWindow( hWnd );

            ::AttachThreadInput( iMyTID, iCurrTID, FALSE );
        }

#endif
    }

我仍然没有在我的项目中提供Mac OS兼容性,因此此代码对非赢平台没有任何功能。

另一个想法:你应该始终保持专注的可见窗口。尝试用WA_TranslucentBackground |做一个WA_TransparentForMouseEvents属性+ FramelessWindowHint标志。因此,您的应用程序永远不会失去焦点。

答案 1 :(得分:6)

所以我设法用平台依赖代码解决了这个问题。我使用.mm文件中的代码创建了Focuser类,其中包含名为Cocoa的Objective-C代码。

focuser.h

#ifndef FOCUSER_H
#define FOCUSER_H

#include <QWidget>

class Focuser {
  QWidget *widget;
public:
  Focuser(QWidget *);
  void show();
  void focus();
};

#endif // FOCUSER_H

focuser_mac.mm

#include "focuser.h"
#import <Cocoa/Cocoa.h>

Focuser::Focuser(QWidget *w) {
  this->widget = w;
}

void Focuser::show() {
  this->widget->show();
  this->focus();
}

void Focuser::focus() {
  [NSApp activateIgnoringOtherApps:YES];
  this->widget->activateWindow();
  this->widget->raise();
}

focuser.cpp

#include "focuser.h"

Focuser::Focuser(QWidget *w) {
  this->widget = w;
}

void Focuser::show() {
  this->widget->show();
  this->focus();
}

void Focuser::focus() {
  this->widget->activateWindow();
  this->widget->raise();
}

所以我们有一个类在构造函数中使用QWidget并且有两个公共方法,一个显示窗口小部件和聚焦小部件的焦点。然后我们有两个类的定义,一个用于Mac OS X的 focuser_mac.mm ,一个用于 focuser.cpp 用于任何其他操作系统。 mac的另外一个叫

[NSApp activateIgnoringOtherApps:YES];

现在,为了编译它,它应该将它添加到 .pro 文件中:

HEADERS += focuser.h

mac {
  OBJECTIVE_SOURCES += focuser_mac.mm
}

linux|win32 {
  SOURCES += focuser.cpp
}

完成后,只需将此代码添加到您需要关注应用程序的位置:

QWidget *w = new QWidget();
// ...
Focuser f(w);
w.show(); // The widget will now be shown and focused by default.