和前面的 一二三四 没有什么连贯性,也没涉及QWidget的派生类,既然是漫谈,我忍了。本文内容:QWidget的创建
起点...
看看本文的代码,是不是很失望?这么简单的一个超级入门级小程序,能有什么可看的?
#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.show();
return a.exec();
}
真的没什么可看的么...
从构造到显示,我们的QWidget的event()函数会依次接收到下面的...这些...事件...
事件type
|
事件type(对应前面的数字)
|
所处代码
|
此时将调用的函数
|
15
|
QEvent::Create
|
QWidgetw;
|
|
203
|
QEvent::WinIdChange
|
w.show();
|
|
75
|
QEvent::Polish
|
QStyle::polish()
|
13
|
QEvent::Move
|
QWidget::moveEvent()
|
14
|
QEvent::Resize
|
QWidget::resizeEvent()
|
17
|
QEvent::Show
|
QWidget::showEvent()
|
24
|
QEvent::WindowActivate
|
|
99
|
QEvent::ActivationChange
|
|
26
|
QEvent::ShowToParent
|
|
74
|
QEvent::PolishRequest
|
a.exec();
|
QWidget::ensurePolished()
|
77
|
QEvent::UpdateRequest
|
QWidgetBackingStore::sync()
|
12
|
QEvent::Paint
|
QWidget::paintEvent()
|
(注:上表是Qt4.7/WinXP下的结果,不同平台下结果会稍有不同,你只需了解这点就好)
如何切入?
如何讨论这个问题,真的很头痛,找不到合适的切入点...
恩,考虑个问题吧?我们知道:
|
X11下
|
Windows 下
|
创建一个窗口
|
XCreateWindow()
|
CreateWindow()
|
显示一个窗口
|
XMapWindow()
|
ShowWindow()
|
自然而然,我们很容易将
但是,我要说的是,这个结论是错误的;创建和显示都是在QWidget::show()内完成的!
有什么用?
了解这些细节有什么用,我直接用不就好了,干嘛要考虑这些乱七八糟的东西呢?
不少人可能遇到过这种问题:
- 在构造函数内获取QWidget的size()和几何尺寸,获取的总是不对
恩,原因就是:构造函数结束时,窗口其实还没有创建,窗口尺寸尚未正式被设置。
废话少说,简单看看源码片段(注,代码中忽略了很多的细节,希望不会对大家造成误导):
构造函数
构造函数中,初始化了大量的参数(我们不关心这些,也不列出了)。我们只看看感兴趣的attribute和事件
void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
{
...
q->setAttribute(Qt::WA_PendingMoveEvent);
q->setAttribute(Qt::WA_PendingResizeEvent);
QEvent e(QEvent::Create);
QApplication::sendEvent(q, &e);
QApplication::postEvent(q, new QEvent(QEvent::PolishRequest));
}
show()
我们都知道,show()、hide()、setHidden()都是setVisible的马甲,所以:
void QWidget::setVisible(bool visible)
{
...
QWidget *pw = parentWidget();
if (!testAttribute(Qt::WA_WState_Created)
&& (isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
create();
}
恩,QWidget::create()在这儿被调用,借助QWidgetPrivate::create_sys使得窗口被创建。此时QEvent::WinIdChange事件通过sendEvent被派发。
// polish if necessary
ensurePolished();
前面提到了,第一调用该函数时,QEvent::Polish事件将通过sendEvent被派发
// activate our layout before we and our children become visible
if (d->layout)
d->layout->activate();
这将通知所有的layout,你们目前的尺寸无效,用到是要重新生成!(额,我们这儿例子中其实没有用到layout)
注意:QLayout是顶级layout负责制,如果你对被嵌套的layout调用activate,最终调用的还是顶级layout(一级一级的向上找)的相应成员。
if (!wasResized
&& (isWindow() || !parentWidget()->d_func()->layout)) {
if (isWindow()) {
adjustSize();
if (windowState() != initialWindowState)
setWindowState(initialWindowState);
} else {
adjustSize();
}
窗口的尺寸是在这儿被调整到合适大小的
if (isWindow() || parentWidget()->isVisible()) {
d->show_helper();
对于show()来说,这是最核心的东西了。
在该函数内,它会检查有无Pending的move或resize的属性。对我们这个,显然是有的。于是 QEvent::Move和QEvent::Resize事件通过sendEvent()被派发
然后派发QEvent::Show事件,随后调用QWidgetPrivate::show_sys()来显示窗口
QEvent showToParentEvent(QEvent::ShowToParent);
QApplication::sendEvent(this, &showToParentEvent);
QApplication::exec()
事件循环,这部分就不介绍。先前通过postEvent()派发的事件以及系统的Spontaneous事件,此时都开始被处理...
PolishRequest
尽管不在此处调用,我们还是看一下PolishRequest将如何被处理:
case QEvent::PolishRequest:
ensurePolished();
如果此时尚未polished,ensurePolished将:给自己发送QEvent::Polish事件,同时递归调用子类的ensurePolished()函数
case QEvent::Polish: {
style()->polish(this);
setAttribute(Qt::WA_WState_Polished);
不过在我们这个例子中,在进入事件循环之前,ensurePolished() 已经被调用多次了。所以此处不会在派发QEvent::Polish事件。
Paint
在X11下,系统的Spontaneous事件 Expose 最终将被转换QEvent::Paint
int QApplication::x11ProcessEvent(XEvent* event)
{
Q_D(QApplication);
...
switch (event->type) {
case GraphicsExpose:
case Expose: // paint event
widget->translatePaintEvent(event);
break;
分享到:
相关推荐
中心部件通常是一个继承自 `QWidget` 的自定义部件,但也可以是其他 `QWidget` 派生类的实例。以下是如何在 `QMainWindow` 中使用中心部件的说明和一个简单的实例讲解。 + **中心部件的使用说明:** 1. **创建中心...
QWidget 直接派生类的样式表不起作用的解决办法,相关教程链接如下: http://blog.csdn.net/tennysonsky/article/details/46653571
026 QWidget类分析显示和隐藏接口说明线程类QThread使用方法.7z
自实现的一个翻转QWidget的demo;采用QPainter和QPropertyAnimation实现,是一个学习动画设计的高效demo
qwidge窗口嵌入qml窗口, qml调用qwidget方法 qwidget发送信号传递数据 qml信号处理以及注意事项
QWidget,QMainWindow和QDialog的区别.
QT 2个QWidget UI 来回切换例子,并且ui界面可自行单独处理单独cpp和h文件,相互不影响。
QWidget嵌入qml,实现QWidget与qml的交互、无标题栏、可拉伸、可拖动、可切换qml页面
两个QWidget互相交换显示
QWidget嵌入Qml界面的小Demo,比较简单的代码,可以提供大家参考!但是还是有一些问题需要大家解决,如果有一些BUG能告知最好
Qt QWidget 互斥抽屉模型Qt QWidget 互斥抽屉模型 Qt5.0~Qt6..4均能编译通过
实现把QWidget嵌入到QML中,实现方案已经在博客中说明。
QT 框接的qwidget实现方法
这里帮大家解决个小难题~环境变量需要你的本机配好~直接就能跑~祝君好运~
本程序实现:单击qml页面,更新按钮的文本;单击按钮,更新qml页面的颜色;展示qml嵌入QWidget方法与通信
内容:QWidget功能作用的展示控件,展示了QWidget功能作用中大小位置的一些API,通过测试,能让自己更快地熟悉其功能作用。 问题:有问题多交流
Qt例程源代码QWidget.7z
需要选择特定区域,所以制作了个区域选择框,在QWidget上绘制区域框,可以放大缩小移动,可以是矩形,也可以是椭圆,注释非常完整。
QWidget控件在QML中使用的控件 具体使用方法在我的博客中详细说明
Qt 使用QWidget调用QML打开安卓摄像头可以实时预览,显示QT中使用QWidget调用QML的方法