Qt 之 WindowFlags 引發的有趣問題一則
轉自:http://blog.csdn.net/dbzhang800/article/details/6680563
來源
來源於 fly542 的一篇blog中描述的一個問題:將一個QMainWindow 作為 QDockWidget的內容widget時,QMainWindow 會作為頂級視窗彈出。
本著精簡的原則,我們提供下面可重現問題的例子:
#include <QtGui/QApplication> #include <QtGui/QMainWindow> #include <QtGui/QDockWidget> #define CASE1 int main(int argc, char *argv[]) { QApplication app(argc, argv); QDockWidget dw; #ifdef CASE1 QMainWindow mw(&dw); #elif defined CASE2 QMainWindow mw; mw.setParent(&dw); #else QMainWindow mw; #endif dw.setWidget(&mw) dw.show(); return app.exec(); }
編譯預處理部分的兩段程式碼會產生什麼不同的結果呢??
QMainWindow mw(&dw); |
會出現兩個視窗,一個是dw,一個是mw |
QMainWindow mw; |
只出現一個視窗dw,而mw是dw的子widget |
QMainWindow mw; |
同上 |
原因何在?
其實,在這之前,我一直認為上面的CASE1和CASE2程式碼是等價的。但現在,顯然不能再這樣認為了。
之所以會這樣,是因為兩種情況下,WindowFlags 標記不同!!前者之所以會彈出,是因為mw是頂級視窗(設定有 Qt::Window 標記位),後者則清除了該標記位。
原始碼
- QMainWindow 構造時會設定 Qt::Window 標記位!
QMainWindow::QMainWindow(QWidget *parent, Qt::WindowFlags flags) : QWidget(*(new QMainWindowPrivate()), parent, flags | Qt::Window) { d_func()->init(); }
- QWidget::setParent 會清除 Qt::Window 標記位!
void QWidget::setParent(QWidget *parent) { if (parent == parentWidget()) return; setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask); }
- QDockWidget如果發現被設定的widget不是自己的子物件,則也輾轉呼叫 QWidget::setParent,進而清除Qt::Window 標記
- 其實是QLayout 提供的功能
void QDockWidget::setWidget(QWidget *widget) { QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(this->layout()); layout->setWidgetForRole(QDockWidgetLayout::Content, widget); } void QLayout::addChildWidget(QWidget *w) { QWidget *mw = parentWidget(); QWidget *pw = w->parentWidget(); ... if (!pw && mw) w->setParent(mw); ... }
疑問??
去掉 dw.show() 後,CASE1 其實仍然會彈出mw視窗。原因何在呢?
答案在:QDockWidget::setWidget 呼叫的函式:
void QDockWidgetLayout::setWidgetForRole(Role r, QWidget *w) { ... if (w != 0) { addChildWidget(w); item_list[r] = new QWidgetItemV2(w); w->show();
會設定 w 可見!!
驗證
貼出另一個例子:感興趣可以自己來做些測試。該說的前面都說了,就不解釋了
#include <QtGui/QApplication> #include <QtGui/QMainWindow> #include <QtGui/QDockWidget> #define CASE3 class MainWindow:public QMainWindow { public: MainWindow() { QDockWidget * dock1 = new QDockWidget(this); #ifdef CASE1 QWidget * w = new QMainWindow(dock1); #elif defined CASE2 QWidget * w = new QMainWindow; #elif defined CASE3 QWidget * w = new QWidget(dock1); w->setWindowFlags(w->windowFlags()|Qt::Window); #endif w->setStyleSheet("background-color: rgb(0, 255, 255);"); dock1->setWidget(w); // dock1->hide(); this->addDockWidget(Qt::LeftDockWidgetArea, dock1); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow w; w.show(); return app.exec(); }
參考
相關文章
- VS開發C++Dll的一些有趣問題C++
- Mybatis 一級快取和引發的問題MyBatis快取
- PHP array_column 引發的一個小問題PHP
- 一個延時任務問題引發的思考
- 一次線上問題排查所引發的思考
- mybatis一級快取(session cache)引發的問題MyBatis快取Session
- Go記憶體架構,一個有趣的問題Go記憶體架構
- 一個引數引發的PDB無法在DataGuard下同步的問題
- 有趣的正則填字遊戲遊戲
- 一個朋友圈泛型問題引發的“案子”泛型
- php使用mysqlnd引發的一些問題處理PHPMySql
- 一個由mobxobserver引發的ReactRoute路由失效問題探究ServerReact路由
- 關於php解構函式的一個有趣問題PHP函式
- 又一個有趣的面試題面試題
- Qt 之 執行Qt Creator出現cannot find -lGL的問題的兩種解決QT
- ASMCMD處理問題一則ASM
- reflow和repaint引發的效能問題AI
- 專案叢集引發的問題
- 一個引發程式設計師們幹架的問題程式設計師
- 一次TiDB GC阻塞引發的效能問題分析TiDBGC
- 關於 http cache 的一個小問題以及引發的思考HTTP
- TSM故障問題解決一則
- MySQL OOM問題處理一則MySqlOOM
- JS語法: 由++[[]][+[]]+[+[]] = 10 ?引發的問題JS
- 有趣的CSS題目(7):消失的邊界線問題CSS
- 使用Hibernate、JPA、Lombok遇到的有趣問題Lombok
- [每日一題]一道面試題是如何引發深層次的靈魂拷問?每日一題面試題
- Flutter實戰之開發問題集(一)Flutter
- 一個有趣的問題: 如何用HashSet來儲存重複的字串?字串
- Qt的目錄依賴問題----怎樣生成一個綠色的Qt軟體包QT
- 一道題引發的EventLoop思考OOP
- 記一個面試題引發的思考面試題
- 一個 Handler 面試題引發的血案!!!面試題
- 一道排序題引發的思考排序
- 一道面試題引發的“血案”面試題
- 一道面試題引發的思考面試題
- 一則無限有趣的Android Messages表情小彩蛋Android
- 一道有趣的golang排錯題Golang