2013-07-01 16 views
10

Mam QSystemTrayIcon z QAction, która otwiera nowe okno typu QWebView. Kiedy okno straci ostrość i ponownie wybiorę QAction, okno powinno odzyskać ostrość. Działa na Linuksie, ale nie na Mac OS X. Problem polega na tym, że kiedy mam inne okno otwarte i aktywne, powiedzmy Google Chrome, kiedy wywołuję show() w oknie, które próbuję otworzyć, to zawsze jest otwierany pod Google Chrome, więc go nie widzę. To samo dotyczy ustawiania ostrości, gdy mam wiele otwartych okien, a mój QWebView może być ostatnim w kolejności, kiedy kliknę przycisk QAction, aby ustawić ostrość okna, zawsze będzie ono wyświetlane w oknie Google Chrome. Domyślam się, że po kliknięciu przycisku QAction, który jest częścią procesu mojej aplikacji, spróbuje otworzyć/zogniskować okno, ale w środku operacji okno przeglądarki Google Chrome zostanie zaplanowane i nabierze ostrości, ponieważ QSystemTrayIcon nie może utrzymać ostrości. Z tego powodu, gdy okno zostanie otwarte/skupione, nie ukradnie fokusu z Google Chrome, ponieważ system operacyjny na to nie zezwala, więc zostanie umieszczony w aktualnie aktywnym oknie.QWidget na Mac OS X nie koncentrując się w Qt 5.x

Oto jak utworzyć/skupić się okno:

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

Czy coś robię nieprawidłowo lub jest jakiś znany obejście?

Odpowiedz

6

Więc udało mi się naprawić problem z kodem zależnym od platformy. Stworzyłem klasę Focuser z kodem w pliku .mm i zawierającym kod Objective-C, który nazwał Cocoa.

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

Mamy więc jedna klasa, która bierze QWidget w konstruktorze i ma dwa publiczne metody, jeden pokaz, który pokazuje widżet i fokus, który skupia widżet. Następnie mamy dwie definicje klasy, jedną dla Mac OS X w focuser_mac.mm i jedną w focuser.cpp dla każdego innego systemu operacyjnego. Jeden dla mac dodatkowo wywołuje

[NSApp activateIgnoringOtherApps:YES]; 

Teraz, w celu użycia go skompilować jak należy dodać do swojej .pro file:

HEADERS += focuser.h 

mac { 
    OBJECTIVE_SOURCES += focuser_mac.mm 
} 

linux|win32 { 
    SOURCES += focuser.cpp 
} 

Kiedy skończysz, po prostu dodaj ten kod tam gdzie potrzeba zgłoszenia się koncentrować:

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

Trochę offtopic, ale może to być przydatne dla niektórych użytkowników:

Moja propozycja jest stworzenie platformy zależało kod, aby wymusić podniesienie okna. Istnieją sam problem na platformie Windows, więc używam następny 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 
    } 

nie ja nadal zapewnić kompatybilność Mac OS w moim projekcie, więc ten kod nie ma funkcjonalność dla platform innych niż wygrać.

Inna idea: powinieneś zawsze utrzymywać skupione widoczne okno. Spróbuj zrobić to za pomocą WA_TranslucentBackground | Atrybuty WA_TransparentForMouseEvents + flaga FramelessWindowHint. Dzięki temu aplikacja nigdy nie straci ostrości.

+0

Niestety, to nie działa w systemie Windows 10 –