一、簡述
前段時間在使用setWindowFlags方法時遇到了一個坑,具體情況是想通過窗口界面上一個checkBox來控制窗口當前狀態是否置頂,而Qt提供了Qt::WindowStaysOnTopHint標志,能夠讓窗口始終保持在其他窗口前端,也就是將窗口置頂。
理論上,我們在勾選上checkBox之后將Qt::WindowStaysOnTopHint標志設置上,就會將窗口置頂,結果卻將窗口隱藏了。那么為什么第二次調用setWindowFlags設置窗口標志位時窗口會隱藏了呢(實際上調用了hide()方法),下面就看一下具體是什么原因導致的。
Qt::WindowStaysOnTopHint
Informs the window system that the window should stay on top of all other windows. Note that on some window managers on X11 you also have to pass Qt::X11BypassWindowManagerHint for this flag to work correctly.
二、分析窗口隱藏原因
首先我們看一下代碼,在構造函數中我們綁定checkBox,然后設置窗口屬性。
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint); connect(ui.checkBox, SIGNAL(stateChanged(int)), this, SLOT(onStateChanged(int)));
checkBox狀態變化槽函數
void onStateChanged(int state) { if (state == Qt::Unchecked) { // 未勾選時不置頂; this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint); } else if (state == Qt::Checked) { // 勾選時置頂; this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowStaysOnTopHint); } }
想要查找原因,那就得直接看Qt源碼呀,所以就直接跟進了qwidget.cpp中的setWindowFlags方法。
調試之后,發現進入了setParent方法,我們仔細看一下,在setParent方法中確實會調用hide方法,那什么時候會調用呢,首先是判斷窗口是否被創建,然后是窗口是否被隱藏,也就是如果窗口被創建並且沒有被隱藏時會調用hide方法。下面是在構造函數中調用setWindowFlags時,wasCreated為false,也不會調用hide,而且當時窗口並未創建,所以在窗口未創建時無論調用多少次setWindowFlags方法,都會以最后一次調用時傳入的參數為准。
下面是在窗口中勾選了checkBox,然后再次調用了setWindowFlags方法,此時滿足窗口被創建並且沒有被隱藏條件,所以這里調用了hide方法將窗口隱藏了,終於找到了原因。
那么也不是沒有辦法解決窗口置頂問題,windows提供了SetWindowPos方法解決了窗口置頂的問題。如果我們想一直保持窗口置頂狀態也可以在窗口初始化時調用setWindowFlags方法傳入Qt::WindowStaysOnTopHint標志即可使窗口置頂。
如果兩個窗口都是置頂狀態,如果層疊在一起也會相互覆蓋。
void onStateChanged(int state) { if (state == Qt::Unchecked) { ::SetWindowPos((HWND)this->winId(), HWND_NOTOPMOST, this->pos().x(), this->pos().y(), width(), height(), SWP_SHOWWINDOW); } else if (state == Qt::Checked) { ::SetWindowPos((HWND)this->winId(), HWND_TOPMOST, this->pos().x(), this->pos().y(), width(), height(), SWP_SHOWWINDOW); } }
http://blog.csdn.net/goforwardtostep/article/details/68938965