2010-05-18 6 views
20
void MainWindow::on_actionAlways_on_Top_triggered(bool checked) 
{ 
    Qt::WindowFlags flags = this->windowFlags(); 
    if (checked) 
    { 
     this->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); 
     this->show(); 
    } 
    else 
    { 
     this->setWindowFlags(flags^(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)); 
     this->show(); 
    } 
} 

La soluzione di cui sopra funziona ma poiché setWindowFlags nasconde la finestra, deve essere nuovamente visualizzata e, naturalmente, non sembra molto elegante. Quindi, come faccio a passare "sempre in primo piano" per una QMainWindow senza quell'effetto collaterale "lampeggiante"?Come si imposta "sempre in primo piano" per QMainWindow in Qt senza causare uno sfarfallio o un flash?

risposta

19

Nokia says no:

Non è possibile apportare modifiche alle bandiere della finestra una volta che la finestra è stata creata senza causare lo sfarfallio. Lo sfarfallio è inevitabile poiché la finestra deve essere ricreata.

Ma a volte se sei bloccato con un effetto lampeggiante che è un po 'brutto come questo, puoi trascinarlo intenzionalmente per far sembrare che qualcosa di "bello" sia appena successo.

Forse si apre una piccola barra di avanzamento che non è nella finestra, dì "Regolazione delle proprietà della finestra!" ... dissolve la finestra fuori dall'esistenza e poi di nuovo dentro, e chiude il popup della barra di avanzamento.

+7

+1: per la bella idea di "soluzione";) – ereOn

+2

Per una funzione "sempre in primo piano", ciò deve essere possibile. Un sacco di applicazioni lo fanno senza sfarfallio; forse ho solo bisogno di utilizzare alcune funzioni native di Windows? –

+1

Se vuoi andare al di sotto o scavalcare l'implementazione Qt (di distruggere la finestra e farlo di nuovo) allora forse. Ma almeno alcune di queste cose sono proprietà del IIRC "Window Class" e non dell'HWND; e potresti non essere in grado di cambiare la classe di una finestra dopo che è stata creata. Ad ogni modo, penso che il valore di fornire una risposta che puoi accettare senza rompere il livello di astrazione Qt è meglio che essere impantanati in hack di Win32. Questa è la gioia di Qt in primo luogo ... – HostileFork

14

Bene, per una soluzione ho pensato di cercare nelle sorgenti Mono, poiché so che la classe .NET Form (System.Windows.Forms) ha una proprietà TopMost.

La soluzione che ho trovato per il mio programma Qt è stato:

void MainWindow::on_actionAlways_on_Top_triggered(bool checked) 
{ 
#ifdef Q_OS_WIN 
    // #include <windows.h> 
    if (checked) 
    { 
     SetWindowPos(this->winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 
    } 
    else 
    { 
     SetWindowPos(this->winId(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 
    } 
#else 
    Qt::WindowFlags flags = this->windowFlags(); 
    if (checked) 
    { 
     this->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); 
     this->show(); 
    } 
    else 
    { 
     this->setWindowFlags(flags^(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)); 
     this->show(); 
    } 
#endif 
} 
+0

Se pensi davvero che ne valga la pena (!), Ma suggerirei almeno di scomporlo come metodo separato, ad es. * void setWindowStaysOnTopHint (bool windowStaysOnTopHint) *. Quindi il tuo ifdef non avrebbe esteso il tuo pulsante e rifletterebbe più accuratamente la routine che "volevi", che Nokia potrebbe aggiungere un giorno se hai inviato una patch per tutte le piattaforme.In quella routine mi sarei anche assicurato di lasciare un link alla domanda SO così qualcuno si chiedesse il motivo per cui è in grado di scoprire ... – HostileFork

+1

L'ho già fatto, ci sono alcuni metodi in una classe separata per gestirlo . L'ho postato qui in questo modo per convenienza se qualcun altro ha mai guardato questa domanda. Interessante idea di inviarlo a Nokia, però, lo prenderò sicuramente in considerazione una volta implementato le soluzioni di lavoro Carbon e X11. –

+1

La risposta è corretta, tuttavia per QT5 c'è la necessità di aggiungere 'reinterpret_cast' a' 'HWND' per this-> WinID()' – Predelnik

-1

testato con

  • Qt 5.2.1 su Windows XP
  • Qt 5.2 su OS X 10,9
 

    void ConsoleUI::onAllwaysTop(bool checked) 
    { 
     Qt::WindowFlags flags = windowFlags(); 
     if (checked) 
     { 
      flags ^= Qt::WindowStaysOnBottomHint; 
      flags |= Qt::WindowStaysOnTopHint; 
     } 
     else 
     { 
      flags ^= Qt::WindowStaysOnTopHint; 
      flags |= Qt::WindowStaysOnBottomHint; 
     } 
     setWindowFlags(flags); 
     show(); 
    } 

+2

Questo è totalmente sbagliato. Prima di tutto imposta la finestra su * sempre in basso * che non si desidera quasi mai (e certamente non è voluto in questa domanda). In secondo luogo, non risponde alla domanda di * come farlo senza sfarfallio *. – Timmmm

Problemi correlati