`
tomhibolu
  • 浏览: 1431458 次
文章分类
社区版块
存档分类
最新评论

漫谈QWidget及其派生类(五)

 
阅读更多

和前面的 一二三四 没有什么连贯性,也没涉及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()

自然而然,我们很容易将

  • 这两个和前面的 QEvent::Create 和 QEvent::Show 对应起来
  • 也很容易将他们和QWidgetw;w.show();对应起来

但是,我要说的是,这个结论是错误的;创建和显示都是在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));
}
  • 两个带Pending的attribute,暂时不谈,稍后我们还会看到它。
  • QEvent::Create 事件,也是我们前面列出的第一个事件!
  • QEvent::PolishRequest事件,注意,这儿采用的postEvent,要到exec()启动以后才会被处理。

show()

我们都知道,show()、hide()、setHidden()都是setVisible的马甲,所以:

  • create()

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被派发。

  • ensurePolished()

        // polish if necessary
        ensurePolished();

前面提到了,第一调用该函数时,QEvent::Polish事件将通过sendEvent被派发

  • QLayout::activate()

        // activate our layout before we and our children become visible
        if (d->layout)
            d->layout->activate();

这将通知所有的layout,你们目前的尺寸无效,用到是要重新生成!(额,我们这儿例子中其实没有用到layout)

注意:QLayout是顶级layout负责制,如果你对被嵌套的layout调用activate,最终调用的还是顶级layout(一级一级的向上找)的相应成员。

  • adjustSize()

        if (!wasResized
            && (isWindow() || !parentWidget()->d_func()->layout))  {
            if (isWindow()) {
                adjustSize();
                if (windowState() != initialWindowState)
                    setWindowState(initialWindowState);
            } else {
                adjustSize();
            }

窗口的尺寸是在这儿被调整到合适大小的

  • show_helper()

        if (isWindow() || parentWidget()->isVisible()) {
            d->show_helper();

对于show()来说,这是最核心的东西了。

在该函数内,它会检查有无Pending的move或resize的属性。对我们这个,显然是有的。于是 QEvent::Move和QEvent::Resize事件通过sendEvent()被派发

然后派发QEvent::Show事件,随后调用QWidgetPrivate::show_sys()来显示窗口

  • 派发QEvent::ShowToParent

        QEvent showToParentEvent(QEvent::ShowToParent);
        QApplication::sendEvent(this, &showToParentEvent);

QApplication::exec()

事件循环,这部分就不介绍。先前通过postEvent()派发的事件以及系统的Spontaneous事件,此时都开始被处理...

PolishRequest

尽管不在此处调用,我们还是看一下PolishRequest将如何被处理:

  • QEvent::PolishRequest

    case QEvent::PolishRequest:
        ensurePolished();

如果此时尚未polished,ensurePolished将:给自己发送QEvent::Polish事件,同时递归调用子类的ensurePolished()函数

  • QEvent::Polish

    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`及其派生类设置背景,创造出美观且符合设计要求的Qt界面。记得在调试过程中,经常使用`show()`方法来实时查看界面效果,以便快速调整样式。

    setCentralWidget,Qt中心部件Demo

    中心部件通常是一个继承自 `QWidget` 的自定义部件,但也可以是其他 `QWidget` 派生类的实例。以下是如何在 `QMainWindow` 中使用中心部件的说明和一个简单的实例讲解。 + **中心部件的使用说明:** 1. **创建中心...

    026 QWidget类分析显示和隐藏接口说明线程类QThread使用方法.7z

    在Qt库中,`QWidget`类是所有用户界面对象的基础,它是构建图形用户界面(GUI)的核心组件。这个压缩包文件“026 QWidget类分析显示和隐藏接口说明线程类QThread使用方法”显然是针对Qt开发者的,旨在详细解释`...

    QWidget嵌入到QML中

    1. 创建`QWidget`:首先,你需要有一个自定义的`QWidget`类。这个类可以继承自`QWidget`,并添加你需要的功能或组件。 ```cpp class CustomWidget : public QWidget { Q_OBJECT public: explicit CustomWidget...

    给QWidget加滚动条

    我们首先需要创建一个继承自`QWidget`的自定义类,这个类将会包含需要展示的内容。在这个类中,我们可以添加布局、按钮、文本等控件。 ```cpp class MyWidget : public QWidget { Q_OBJECT public: MyWidget...

    Qt例程源代码QWidget.7z

    这个"Qt例程源代码QWidget.7z"压缩包显然是一个包含Qt编程示例的资源,特别是关于QWidget类的使用。QWidget是Qt GUI库中的基础组件,它是所有用户界面对象的基类,包括按钮、文本框、菜单等。 在Qt中,QWidget主要...

    使用QWidget实现翻转

    1. 创建一个继承自`QWidget`的自定义类,并重写`paintEvent()`方法。在这里,你需要绘制翻转前后的两个图像或内容。通常,这会涉及设置`QPainter`的画刷和画笔,然后在指定区域内绘制。 2. 在`paintEvent()`中,...

    2个QWidget相互切换显示.zip

    `QWidget`是QT库中的核心类,它提供了图形用户界面的基础框架,包括窗口、控件和布局管理等。每个`QWidget`都可以有自己的子部件,并且可以通过布局来组织这些子部件,使其在窗口中按照预期的方式排列。 在描述中...

    qwidget嵌入qml最完整代码

    QML是一种基于JSON的声明式语言,用于构建具有丰富图形界面的应用程序,而QWidget是C++中的一个类,它是Qt GUI编程的核心组件。在某些场景下,我们需要将两者结合使用,以利用QML的灵活性和QWidget的功能性。...

    QWidget控件在QML中使用 控件

    在Qt框架中,QML(Qt Quick)是一种强大的声明式用户界面设计语言,它允许开发者...这种方式不仅适用于QWidget,还可以应用于其他C++类,如自定义的QGraphicsView或复杂的逻辑处理类,让QML和C++的优点得到充分的结合。

    QML与QWidget交互

    4. **使用`Q_INVOKABLE`和`Qt::DirectConnection`**:在C++类中定义`Q_INVOKABLE`方法,使其能在QML中调用,使用`Qt::DirectConnection`确保方法立即执行。 ```cpp // C++ class MyData : public QObject { Q_...

    qwidget与qml交互

    QML是一种基于JSON的声明式语言,用于构建具有丰富图形界面的应用程序,而QWidget是C++中的一个类,它是Qt GUI系统的基础,用于创建窗口和控件。当我们需要将传统C++的QWidget组件与QML的灵活性结合时,就会涉及到...

    QWidget嵌入Qml界面.zip

    标签"QWidget Qt Qt5 Qml QWidget嵌入Qml"明确了主要涉及的技术领域:`QWidget`(Qt的窗口和控件基础),Qt库(一个跨平台的应用程序开发框架),Qt5版本(该示例可能基于Qt的第五个主要版本),以及`QML`(用于构建...

    QWidget,QMainWindow和QDialog的区别

    QWidget、QMainWindow 和 QDialog 是 Qt 中三个基础的 GUI 组件类,它们之间的区别是非常重要的,在创建 Qt Gui Application 时,总会让你选择在 QWidget、QMainWindow 和 QDialog 中选择一个 Base Class。这三个类...

    使用QT编写的窗口句柄查看器 Spy++,源码奉献

    使用QT编写的窗口句柄查看器,拖动准星...一个可拖动的准星类:准星拖动以一个QWidget的派生类实现,在此类中,鼠标左键按下发出开始信号,左键释放发出停止信号。按下并拖动过程中,将准星QWidget移动到鼠标所在位置。

    两个QWidget互相交换显示

    1. **使用QStackedWidget**:QStackedWidget是一种容器类,它可以包含多个子窗口部件,并在需要时切换显示。只需将两个QWidget实例添加到QStackedWidget中,然后通过`setCurrentIndex()`方法切换显示的QWidget。例如...

    qwidgets_qwidget和qwidgets_qtqwidget_

    通常,开发者并不直接与QtQWidget打交道,而是通过QWidget及其子类来间接使用其功能。 在实际编程中,理解QWidgets和QtQWidget的区别很重要。QWidgets提供的是面向用户的高级接口,而QtQWidget是实现这些接口的底层...

    QWidget 显示图片,支持缩放、拖动、右键菜单等功能

    本示例中,我们关注的是一个扩展了`QWidget` 的类,它增加了显示图片、支持缩放、拖动以及右键菜单的功能。这个自定义的组件名为 `MyImageWidget`。 首先,`MyImageWidget` 类会继承自`QWidget`,以便我们可以利用`...

    QT C++ QWidget 自定义头窗口头标+毛玻璃效果

    在QT C++编程环境中,`QWidget`是所有用户界面组件的基础类,它是构建GUI应用程序的核心。本教程将探讨如何利用`QWidget`自定义一个带有独特头部设计和毛玻璃效果的窗口。毛玻璃效果,又称模糊效果,能为窗口提供半...

    QWidget无标题窗口,可随意缩放拖动

    在IT行业中,特别是GUI编程领域,`QWidget`是Qt库中的一个核心类,用于构建用户界面的基本元素。本文将深入探讨如何使用C++和Qt库创建一个无标题、可自由缩放和拖动的窗口。 首先,让我们了解`QWidget`。`QWidget`...

Global site tag (gtag.js) - Google Analytics