天天看点

QWidget Z-Order研究Z-OrderQML Z-OrderQWidget Z-Order总结

Z-Order

Z-Order指的是三维坐标系中的Z轴顺序,而在系统视图中,X轴和Y轴往往表示平面的宽高方向(可以理解为显示器的宽高),而Z轴表示屏幕到视线的方向,如下图所示:

QWidget Z-Order研究Z-OrderQML Z-OrderQWidget Z-Order总结

所以Z轴的坐标会影响人看到的东西,在X和Y坐标一样,且大小一致的两个Item中哪个能被用户看到,取决于Z轴的坐标,Z轴值大的覆盖小的。

QML Z-Order

QML中Item有一个属性z,该属性能够控制Item的Z轴值,具体介绍可以参考官网Item

QWidget Z-Order

QWidget中并没有关于Z-Order的属性,经过一些测试后发现虽然QWidget没有关于Z-Order的属性,但是其通过其他方式实现了。

一开始查找资料的时候只发现以下三个接口:

// 将当前Widget放到父窗口组件堆栈中的w窗口的下面(在视觉效果上就是Widget被w窗口掩盖)
void QWidget::stackUnder(QWidget *w)

// 将当前Widget上升到父窗口组件堆栈的顶部(在视觉效果上会掩盖住同堆栈内的其他Widget)
void QWidget::raise()

// 将当前Widget降低到父窗口组件堆栈的底部(在视觉效果上会被同堆栈内的其他Widget掩盖)
void QWidget::lower()
           

从这些接口的注释可以看出child widget在父窗口对象中是用一个堆栈维护的,这里我就联想到QObject对象会维护一个QObjectList,在析构的时候先行析构child object。难道这个QObjectList和Z-Order有关系?那就测试一下吧:

测试方法是两个子窗口通过鼠标双击调用raise()实现以下效果:

QWidget Z-Order研究Z-OrderQML Z-OrderQWidget Z-Order总结

看一下主要代码:

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    for (int i = 0; i < 2; i++) {
        widgets[i] = new ChildWidget(this);
        widgets[i]->setText(QString("order%1").arg(i));
        widgets[i]->setObjectName(QString("order%1").arg(i));
        connect(widgets[i], &ChildWidget::sigDBClicked, this, &Widget::onChildDbClicked);
    }
    widgets[0]->setStyleSheet("background: red;");
    widgets[0]->move(10, 10);
    widgets[1]->setStyleSheet("background: black;");
    widgets[1]->move(210, 50);

    qDebug() << "----------";
    for (auto obj : this->children()) {
        qDebug() << obj;
    }
    qDebug() << "----------";
}

// slot
void Widget::onChildDbClicked()
{
    qDebug() << "----------";
    static_cast<ChildWidget*>(sender())->raise();
    for (auto obj : this->children()) {
        qDebug() << obj;
    }
    qDebug() << "----------";
}
           

通过gif和代码可以看出raise()函数修改的父窗口组件堆栈其实就是父Object的children。那么parent Widget在显示child Widgets时就是通过QObjectList来处理的,先添加的child Widget会被后添加的parent Widget覆盖。

总结

  1. QWidget的视觉Z-Order可以通过stackUnder、lower、raise三个函数来修改
  2. 初始化的Z-Order和添加child Widget的先后有关

继续阅读