Qt z-order 研究

Qt z-order 研究

当用一个label 盖压另一个label 时, 遇到了一些问题, 就是达不到自己的期望操作.
所以认真研究了一下z-order 序
下面程序可以揭示qt z-order 是如何实现的?  背后的道理是什么?

QtWidget 下有三个函数与z-order 相关,
raise(),lower(),stackUnder(),

看一下raise() 在assistant 文档中的描述(要学会用assistant,因为头文件中没写), 其它2个类似
[slot] void QWidget::raise()
Raises this widget to the top of the parent widget's stack.
After this call the widget will be visually in front of any overlapping sibling widgets.
Note: When using activateWindow(), you can call this function to ensure that the window is stacked on top.
See also lower() and stackUnder().

提升这个控件到父控件堆栈的顶部. 调用该函数后,这个控件将是可见的,在其它兄弟控件的顶部.
注意: 当使用activateWindow(), 你可以调用这个函数保证窗口在堆栈顶部.

另两个函数是保证在堆栈底部和某控件下方.

从这些描述中我们看到, z 序是通过父控件的堆栈来维护的. 什么意思呢? 网上有人言, 这个堆栈序就是QObjectList 顺序.
现在做一下测试: 证明确实如此:
本人精心打造如下测试程序,从测试程序中学到了:
1. qt 中的z-order 是如何实现的, 我们如何控制z-order
2. 如何获取object 上的指定事件. 可以通过安装eventfilter, 过滤(找到obj,event)我们感兴趣的事件.
3. qt stylesheet 及 align 的数学(可借助qtcreator)

主题文件: mainwindow.h, mainwindow.cpp

$ cat mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWidget>
#include <QLabel>
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow(){};
    QWidget* cwidget;
    QLabel* label1;
    QLabel* label2;
    QLabel* label3;
	bool eventFilter(QObject *obj, QEvent * ev);   //过滤鼠标双击事件
private:
	void printStackOrder();
};

#endif // MAINWINDOW_H
$ cat mainwindow.cpp 
#include "mainwindow.h"
#include <QDebug>
#include <QEvent>


MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
	resize(500,500);	// 重新设置窗口大小
    cwidget = new QWidget;
    this->setCentralWidget(cwidget);	//QMainWindow 都有一个CentralWidget
	//创建3个label, 其父对象为cwidget
    label1 = new QLabel(cwidget);
	label1->setObjectName("label1");
	label1->setText("label1");
    label1->setAlignment(Qt::AlignHCenter|Qt::AlignTop);
    label1->setStyleSheet("font:20pt;background-color: red;");
    label1->setGeometry(0,0,300,300);

    label2 = new QLabel(cwidget);
	label2->setObjectName("label2");
	label2->setText("label2");
    label2->setAlignment(Qt::AlignHCenter|Qt::AlignTop);
    label2->setStyleSheet("font:20pt;background-color: green;");
    label2->setGeometry(100,100,300,300);

    label3 = new QLabel(cwidget);
	label3->setObjectName("label3");
	label3->setText("label3");
    label3->setAlignment(Qt::AlignHCenter|Qt::AlignTop);
    label3->setStyleSheet("font:20pt;background-color: blue;");
    label3->setGeometry(200,200,300,300);

	label1->installEventFilter(this); //过滤本窗口上的事件
	label2->installEventFilter(this);
	label3->installEventFilter(this);
	qDebug()<<"label1:"<<label1;
	qDebug()<<"label2:"<<label2;
	qDebug()<<"label3:"<<label3;
	printStackOrder();
}

void MainWindow::printStackOrder()
{
	QObjectList list = cwidget->children(); //获取centralWidget 的子对象列表
	QList<QObject*>::iterator it;
	qDebug()<<"-----begin-----";
	for(it=list.begin(); it!=list.end(); it++)
	{
		qDebug()<<"obj:name"<<(*it)->objectName();
	}
}

bool MainWindow::eventFilter(QObject *obj, QEvent * ev)   
{
//	qDebug()<<"event happen! obj:"<<obj;	//所有过滤的obj 及事件都会到这里来
	if (ev->type() == QEvent::MouseButtonDblClick) // 你要过滤的对象的事件类型,过滤鼠标双击事件
	{
		if (obj == label1) // 你要过滤的对象
		{
			qDebug()<<"lablel1 double cliked!";	
			printStackOrder();
			label1->raise();
			printStackOrder();
			return true; // 注意这里一定要返回true,表示事件处理就结束了.
		}
		else if (obj == label2) // 你要过滤的对象
		{
			qDebug()<<"lablel2 double cliked!";	
			label2->raise();
			printStackOrder();
			return true; 
		}
		else if (obj == label3) // 你要过滤的对象
		{
			qDebug()<<"lablel3 double cliked!";	
			label3->raise();
			printStackOrder();
			return true;
		}
	}
	return false; // 返回false表示不过滤,事件还按默认的方式处理
}

辅助文件:main.cpp, project 文件

$ cat main.cpp 
#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
	QApplication app(argc,argv);
	MainWindow *mainw = new MainWindow;
	mainw->show();
	return app.exec();
}
 cat z-order.pro 
######################################################################
# Automatically generated by qmake (3.1) Sun Apr 10 10:44:08 2022
######################################################################

TEMPLATE = app
TARGET = z-order
INCLUDEPATH += .
QT+=widgets

# You can make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# Please consult the documentation of the deprecated API in order to know
# how to port your code away from it.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

# Input
HEADERS += mainwindow.h
SOURCES += main.cpp mainwindow.cpp

附图1: 开始时的z-order 序

 双击label1后:

运行结果:

./z-order 
label1: QLabel(0x55adcf593e40, name="label1")
label2: QLabel(0x55adcf515710, name="label2")
label3: QLabel(0x55adcf50d320, name="label3")
-----begin-----
obj:name "label1"
obj:name "label2"
obj:name "label3"   // 开始时的z-order 序, 按label创建顺序, label3在尾部,有最高显示级别
lablel1 double cliked!
-----begin-----
obj:name "label2"
obj:name "label3"
obj:name ""       //多出一个空obj
obj:name "label1" //双击label, 提升label1 z-order序, 此时其处于堆栈尾部,有最高显示级别.

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值