天天看點

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的先後有關

繼續閱讀