QWidget的isHidden和isVisible
QWidget的isHidden和isVisible
问题的出现
最近在写代码的时候,出现了一个问题,我新建了两个类,分别是Chapter2和ConsecutiveCurtain
// ConsecutiveCurtain.cpp
ConsecutiveCurtain::ConsecutiveCurtain(QWidget *parent)
:QWidget(parent)
{
number = 1;
this->setFixedSize(1920, 1080);
}
void ConsecutiveCurtain::start()
{
if (m_curtainList.isEmpty()) {
qDebug() << "显示列表为空";
return;
}
m_curtain = new Curtain(m_curtainList.at(0), this);
connect(m_curtain, &Curtain::signal_pageEnd,
this, &ConsecutiveCurtain::slot_nextPage, Qt::UniqueConnection);
m_curtain->start();
}
// chapter2.cpp
Chapter2::Chapter2(QWidget *parent)
:QWidget(parent)
{
m_curtains = new ConsecutiveCurtain(this);
this->start();
}
void Chapter2::slot_Curtains1()
{
m_phone->close();
QStringList curtains;
curtains.push_back("chapter2_4.png");
curtains.push_back("chapter2_5.png");
curtains.push_back("chapter2_6.png");
curtains.push_back("chapter2_7.png");
m_curtains->setCurtainList(curtains);
connect(m_curtains, &ConsecutiveCurtain::signal_consecutiveCurtainEnd,
this, &Chapter2::slot_Phone2);
m_curtains->start();
m_curtains->show();
}
,这几个的结构如图所示:

但是在我新建ConsecutiveCurtain这个类的实例,并在chapter2.cpp中show()时,什么都没有显示。
我左思右想,发现了两种解决方法:
第一种方法是:
ConsecutiveCurtain::ConsecutiveCurtain(QWidget *parent)
:QWidget(parent)
{
number = 1;
this->setFixedSize(1920, 1080);
this->hide();
}
在ConsecutiveCurtain类里调用this->hide(),之后就可以正常显示了。
第二种方法是:
void ConsecutiveCurtain::start()
{
if (m_curtainList.isEmpty()) {
qDebug() << "显示列表为空";
return;
}
m_curtain = new Curtain(m_curtainList.at(0), this);
connect(m_curtain, &Curtain::signal_pageEnd,
this, &ConsecutiveCurtain::slot_nextPage, Qt::UniqueConnection);
m_curtain->show();
m_curtain->start();
}
在start()函数里调用m_curtain->show()
两种方法都可以显示出来,于是我开始纠结,为啥会显示。第二方法我还是能理解的,因为直接把m_curtain显示出来了。但是第一种方法的调用hide()函数后,就可以显示的问题,使我百思不得其解。
QWidget的show()函数
在我印象中,show()是会将调用者和调用者的子窗口也一起show出来,于是我就有了一个疑问,在chapter2::slot_Curtains1函数中,我调用了m_curtains->show(),按道理是会将Consecutive中的m_curtain一起show()出来的。

于是我去看QWidget的源码,发现所有的show()函数,都是调用的setVisible()这一个函数。
void QWidgetPrivate::setVisible(bool visible)
{
Q_Q(QWidget);
if (visible) { // show
// Designer uses a trick to make grabWidget work without showing
if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
&& !q->parentWidget()->testAttribute(Qt::WA_WState_Created))
q->parentWidget()->window()->d_func()->createRecursively();
//create toplevels but not children of non-visible parents
QWidget *pw = q->parentWidget();
if (!q->testAttribute(Qt::WA_WState_Created)
&& (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
q->create();
}
这里的createRecursively则是去递归的show子窗口,这里是否创建子窗口有一个判断依据,那就是子窗口的isHidden是不是返回的false,也就是说子窗口是不是没有被隐藏。
void QWidgetPrivate::createRecursively()
{
Q_Q(QWidget);
q->create(0, true, true);
for (int i = 0; i < children.size(); ++i) {
QWidget *child = qobject_cast<QWidget *>(children.at(i));
if (child && !child->isHidden() && !child->isWindow() && !child->testAttribute(Qt::WA_WState_Created))
child->d_func()->createRecursively();
}
}
QWidget的isVisible和isHidden
在找寻为什么调用hide()之后,就能正常显示时,我发现了这两个函数isVisible和isHidden,然后我用这两个函数加到代码里做测试(得到正确的测试方法不知道走了多少弯路)
void Chapter2::slot_Curtains1()
{
m_phone->close();
qDebug() << m_curtains->isVisible();
QStringList curtains;
curtains.push_back("chapter2_4.png");
curtains.push_back("chapter2_5.png");
curtains.push_back("chapter2_6.png");
curtains.push_back("chapter2_7.png");
m_curtains->setCurtainList(curtains);
connect(m_curtains, &ConsecutiveCurtain::signal_consecutiveCurtainEnd,
this, &Chapter2::slot_Phone2);
m_curtains->start();
m_curtains->show();
qDebug() << m_curtains->isVisible();
}
void ConsecutiveCurtain::start()
{
if (m_curtainList.isEmpty()) {
qDebug() << "显示列表为空";
return;
}
m_curtain = new Curtain(m_curtainList.at(0), this);
connect(m_curtain, &Curtain::signal_pageEnd,
this, &ConsecutiveCurtain::slot_nextPage, Qt::UniqueConnection);
qDebug() << "m_curtain visible :" << m_curtain->isVisible();
qDebug() << "m_curtain hidden :" << m_curtain->isHidden();
m_curtain->start();
}
在不调用hide()函数时,输出如下:
true
m_curtain visible : false
m_curtain hidden : true
true
调用hide()函数后,输出如下:
false
m_curtain visible : false
m_curtain hidden : false
true
然后我在查阅isHidden这个函数的手册时,发现如下解释:

到这里,我就恍然大悟:
如果不调用hide()函数,ConsecutiveCurtain的实例就不会隐藏,这样,m_curtain也就会被设置成隐藏,哪怕你show出父窗口,子窗口也会因为被隐藏这个原因,而不显示。
源码追溯
于是我又试着去源码里找这一部分的实现方法:
这是QWidget类的构造函数

我又溯源到init()函数…

这里我发现了一个q->setAttribute(Qt::WA_WState_Hidden);,这里相当于默认就给新建的窗口设置为隐藏,但是也没有找到帮助文档里所说的,于是我又继续往下寻找,我发现了一个setParent()函数

我找到这个setParent函数,

然后再setParent里找到了这个setParent_sys

最终,我在这个setParent_sys里找到了这一句代码,也就是说,如果新设置的parent是可见的,就将当前窗口设置成隐藏属性。

至此,就找出了所有问题的答案…
第一次看源码来找问题,虽然找了大半个下午,但是找到的那一瞬间真的是超级开心…
QWidget的isHidden和isVisible的更多相关文章
- 微软出品自动化神器【Playwright+Java】系列(七) 之 元素的可操作性验证
前言 昨天在某平台发表了一篇这系列的文章,结果不但提示说有违禁词(java也算?),然后文章审核通过后,文章还找不到,不到去哪了,表示很郁闷,去反应未果,确实有点尴尬了. 元素的可操作性验证 关于AP ...
- GUI学习之四——QWidget控件学习总结
上一章将的QObject是PyQt里所有控件的基类,并不属于可视化的控件.这一章所讲的QWidget,是所有可视化控件的基类. QWidget包含下面几点特性 a.控件是用户界面的最小的元素 b.每个 ...
- QWidget窗口类
import sys from PyQt5.QtWidgets import QWidget, QApplication,QPushButton from PyQt5.QtGui import QIc ...
- QWidget类参考
QWidget类是所有用户界面对象的基类. 详情请见…… #include <qwidget.h> 继承QObject和QPaintDevice. 被QButton.QFrame.QDia ...
- PyQt5学习 (3)--QWidget(下)
层级关系.层级控制: 调整Z轴顺序 点击查看代码 label1 = QLabel(window) label1.setText("标签1") label1.resize(200, ...
- Qt:QWidget
0.说明 QWidget类是所有用户界面对象的基类. QWidget是用户界面的原子类.它接收鼠标.键盘和来自系统的其他事件,并在屏幕上将它们绘制出来.每个Widget都是矩形的,并按照Z-order ...
- QDialog QMainwindow QWidget QFrame不同时候用法.
继承关系:在Qt中所有的类都有一个共同的基类QObject ,QWidget直接继承与QPaintDevice类,QDialog.QMainWindow.QFrame直接继承QWidget 类. ...
- MainWindow、QWidget和QDialog的区别和选择(转载)
QApplication类用于管理应用程序范围内的资源,其构造函数需要main函数的argc和argv作为参数. Widget被创建时都是不可见的,widget中可容纳其他的widget. Qt中的w ...
- QWidget 实现 打破布局 或者 当前窗体内的 弹窗 (借助伪造实现)
but = QtWidgets.QToolButton(Dialog2) but.setText('**') but.setAutoRaise(True) layout.addWidget(but) ...
- [转载] - QWidget、QMainWindow、QDialog和QFrame的区别
继承关系:在Qt中所有的类都有一个共同的基类QObject ,QWidget直接继承与QPaintDevice类,QDialog.QMainWindow.QFrame直接继承QWidget 类. ...
随机推荐
- 【转载】获取Java接口的所有实现类
https://www.cnblogs.com/wangzhen-fly/p/11002814.html 前言:想看基于spring 的最简单实现方法,请直接看 第七步. 本文价值在于 包扫描的原理探 ...
- Qt/C++编写视频监控系统80-远程回放视频流
一.前言 远程回放NVR或者服务器上的视频文件,一般有三种方式,第一种是调用厂家的SDK,这个功能最全,但是缺点明显就是每个厂家的设备都有自己的SDK,只兼容自家的设备,如果你的软件需要接入多个厂家的 ...
- [转]When allowCredentials is true, allowedOrigins cannot contain the special value “*“
前言 项目接口访问出现allowedOrigins cannot contain the special value "*" java.lang.IllegalArgumentEx ...
- dotnet最小webApi开发实践
dotnet最小webApi开发实践 软件开发过程中,经常需要写一些功能验证代码.通常是创建一个console程序来验证测试,但黑呼呼的方脑袋界面,实在是不讨人喜欢. Web开发目前已是网络世界中的主 ...
- .Net程序员机会来了,微软官方新推出一个面向Windows开发者本地运行AI模型的开源工具
想要开发AI产品的.Net程序员机会来了,这个项目应该好好研究. 虽然说大模型基本都有提供网络API,但肯定没有直接使用本地模型速度快. 最近微软官方新推出AI Dev Gallery开源项目,可以帮 ...
- sql server版本太老,java客户端连接失败问题定位
背景 最近半路接手了一个系统的优化需求,这个系统有个遗留问题还没解决,随着新需求的上线,系统正式开放使用,这个遗留问题也必须解决. 这个系统大概是下面这样的,支持录入各种数据源的信息(ip.端口.数据 ...
- 树莓派Zero OLED屏幕转接板
买了个树莓派Zero,emmm,拿到手后感觉很精巧,但是总是感觉少了什么.于是... 瞎吹一波:不得不说嘉立创公司确实给力,一条龙服务而且价格太便宜了. 焊接组装上机测试,OK! 其实这个过程中坑也踩 ...
- asp.net core中,使用CancellationToken在用户终止请求时取消所有异步操作+ abp中的设计
如果一个Controller.Action里的处理非常耗时,比如读数据库.文件操作.调用第三方接口等此时用户随时可能关闭浏览器.F5刷新网页等操作.但是服务端的耗时代码任然在执行,这太浪费了,既然用户 ...
- Java中String类常用的各种方法
Java中String类常见的方法 以下介绍字符串常见的几个方法. 介绍String类 在 Java 中,String 类是一个代表字符串的类,具有以下特性: 不可变性:String 对象一旦被创建就 ...
- Spring常用注解介绍
在Spring中,有许多高效的注解,其简化了开发并提高代码可读性,这样我们就不用再去spring.xml文件中写标签了非常方便 创建对象的注解 在Spring,有用于识别不同类型的Bean,使得Spr ...