对于QWidget,总觉得该写点什么。可又不知道具体该写些什么,思路又乱又杂。简单理理,简单写写,就叫漫谈吧
注意:我不知道本文写完会是什么样子,可能写着写着就没下文了。也可能各部分隔很长时间。
注意:本系列涉及到的东西都是Qt用户需要理解的,但是,我们不应该在实际项目中这么用。
QWidget
QWidget 是Qt中所有widget部件(比如QDialog、QPushButton、QLabel)的基类。
- 任何你可以通过其派生类实现的东西,你都可以通过QWidget实现(只要你不怕麻烦)
比如:
QDialog有模态非模态之说 |
QWidget 有没有?当然有,不要怀疑 |
QDialog dlg(this)是一个窗口 |
QWidget wgt(this)能不能是窗口?当然行 |
QMainWindow可以有菜单栏、工具栏等 |
QWidget 可不可以加?当然可以,只要你需要 |
... |
... |
Window 与 Widget
Qt中的部件有Window和普通widget之说:
Window |
窗口 |
Window是这样的Widget:它不是其他Widget的一部分区域,通常有标题栏等窗口装饰器!(和是否有parent无关) |
Widget |
普通部件(非窗口) |
除Window外的部件 |
如何可以知道一个widget是否是Window?注意:QWidget::isWindow()
inline bool QWidget::isWindow() const { return (windowType() & Qt::Window); }
呵呵,不小心将源码给出了,那就继续吧,
windowType() 是什么东西?为了避免混乱,我将它和windowFlags()同等看待(其中的细微区别不会影响我们的分析)
看看下面的函数:
QWidget::QWidget(QWidget * parent = 0, Qt::WindowFlags f = 0 ) void QWidget::setWindowFlags(Qt::WindowFlags type ) QDialog::QDialog(QWidget * parent = 0, Qt::WindowFlags f = 0 ) ...
恩,你可以通过构造函数或者成员函数setWindowFlags传递这个参数。 而且,你从前面的isWindow()的源码可以得出结论: 一个Widget是不是一个Window,只取决于它的的WindowFlags中是否包含Qt::Window
对么??
你会不会说:不对!!!
- 例子一
比如:一个QPushButton,如果没有parent,它就是一个窗口。而设置了parent,它却不是一个窗口了。分明就是和是否有parent相关嘛!(这种例子太常见了,对吧)
- 例子二
恩,再看一个很多人迷惑的例子:在一个函数内
void Widget::onXXXX() { QDialog * dlg = new QDialog(this); //QWidget * dlg = new QWidget(this); dlg->show(); }
如果用 QDialog,则会出现一个窗口,而如果用 QWidget,则不会出现窗口(而是一个普通部件)。为什么啊?都有parent啊?为什么会这样??
其实:例子一是特例,原因就是前面提到的,是否是窗口取决于flags,而不是有无parent
原因
记住前面的黑体部分!
对于QWidget,如果其parent为空,构造时会有下面的动作:
uint type = (flags & Qt::WindowType_Mask); if ((type == Qt::Widget || type == Qt::SubWindow) && w && !w->parent()) { type = Qt::Window; flags |= Qt::Window; }
注意看,如果一个widget没有parent,且没有Qt::Window标记,会被强制设置该标记(如果有parent,就不会设置标记了)。这就是parent的影响,也是上面例子一的答案。
可是第二个例子怎么回事?QDialog默认的flags也是0啊,也就parent,为啥还是窗口呢??
QDialog::QDialog(QWidget *parent, Qt::WindowFlags f) : QWidget(*new QDialogPrivate, parent, f | ((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0))) { ...
答案很简单,QDialog是派生类嘛,它构造函数中传给基类的参数包含了Qt::Dailog(即0x00000002|Qt::Window)。既然包含了Qt::Widnow标记,当然就和是否有parent无关喽!(例子一其实才是特例,只不过大家见的多了,反倒习以为常了)
- 例子三
感兴趣的看看,会有什么结果,嘿嘿,本节完
QPushButton * btn = new QPushButton(this); btn->setWindowFlags(Qt::Window);
作者:dbzhang800