2013-07-01 74 views
10

我有QSystemTrayIcon和QAction,打開QWebView類型的新窗口。當窗口失去焦點並且我再次選擇QAction時,窗口應該重新獲得焦點。它在Linux上運行,但不在Mac OS X上運行。問題是,當我打開另一個窗口並處於活動狀態時,讓我們說谷歌瀏覽器,當我在打開的窗口中調用show()時,它總是在Google Chrome瀏覽器下打開,所以我沒有看到它。聚焦也是一樣,當我打開多個窗口時,我的QWebView可能是順序中的最後一個,當我點擊QAction來關注窗口時,它總是在Google Chrome窗口下。我的猜測是,當我單擊QAction(這是應用程序進程的一部分)時,它會嘗試打開/關注窗口,但在操作過程中,Google Chrome窗口會進行調度並獲得焦點,因爲QSystemTrayIcon不能持有重點。因此,當窗口被打開/關注時,它不會從Google Chrome中竊取焦點,因爲操作系統不允許它,所以它將被置於當前聚焦的窗口之下。Mac OS X上的QWidget沒有專注於Qt 5.x

在這裏,我如何創建/聚焦窗口:

// ... 
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(); 
    } 
} 

有什麼我做的不正確或是否有任何已知的解決方法嗎?

回答

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.mmfocuser.cpp中的一個用於任何其他操作系統。在一個爲Mac還要求

[NSApp activateIgnoringOtherApps:YES]; 

現在,爲了它來編譯,因爲它應該添加到您的。親文件:

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. 
6

有點offtopic,但它可能對一些用戶來說是有益的:

我的建議是建立平臺的依賴代碼強制窗口的認識。有在Windows平臺上同樣的問題,所以我用劈旁邊:

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標誌。所以你的應用永遠不會放鬆焦點。

+0

不幸的是,這在Windows 10不工作 –