Z-Order
Z-Order指的是三維坐标系中的Z軸順序,而在系統視圖中,X軸和Y軸往往表示平面的寬高方向(可以了解為顯示器的寬高),而Z軸表示螢幕到視線的方向,如下圖所示:

是以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()實作以下效果:
看一下主要代碼:
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覆寫。
總結
- QWidget的視覺Z-Order可以通過stackUnder、lower、raise三個函數來修改
- 初始化的Z-Order和添加child Widget的先後有關