QT中的模态对话框及非模态对话框

news2024/11/29 22:46:45

QT中的模态对话框及非模态对话框

  • [1] QT中的模态对话框及非模态对话框
  • [2] Qt工作笔记-主界面往模式对话框emit信号,有注意的问题
    • 正常情况下:
    • 不正常情况下:
    • 下面给出正常情况下的代码:


[1] QT中的模态对话框及非模态对话框

原文链接:https://blog.csdn.net/u011555996/article/details/108110925

模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在。又有叫法是称为模式对话框,无模式对话框等。所谓模态对话框就是在其没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭。对于非模态对话框,当被打开时,用户既可选择和该对话框进行交互,也可以选择同应用程序的其他窗口交互。

在Qt中,显示一个对话框一般有两种方式,一种是使用exec()方法,它总是以模态来显示对话框;另一种是使用show()方法,它使得对话框既可以模态显示,也可以非模态显示,决定它是模态还是非模态的是对话框的modal属性。

在Qt中,Qt的模态与非模态对话框选择是通过其属性modal来确定的。我们来看看modal属性,其定义如下:

modal : bool默认情况下,对话框的该属性值是false,这时通过show()方法显示的对话框就是非模态的。而如果将该属性值设置为true,就设置成了模态对话框,其作用于把QWidget::windowModality属性设置为Qt::ApplicationModal。

而使用exec()方法显示对话框的话,将忽略modal属性值的设置并把对话框设置为模态对话框。

一般使用setModal()方法来设置对话框的modal属性。

我们总结一下设置对话框为模态的方法。

◆ 如果要设置为模态对话框,最简单的就是使用exec()方法,示例代码如下:

MyDialog myDlg;
myDlg.exec(); 
//也可以使用show()方法,示例代码如下:

MyDialog myDlg;    
myDlg.setModal(true);    
myDlg.show();

◆ 如果要设置为非模态对话框,必须使用show()方法,示例代码如下:

MyDialog myDlg;
myDlg.setModal(false);
//或者
myDlg.setModal();
myDlg.show();

再次强调,目前有的朋友对于模态对话框和非模态对话框的认识有误解,认为使用show()方法显示的就是非模态对话框,这是不正确的。

小贴士:有时候,我们需要一个对话框以非模态的形式显示,但又需要它总在所有窗口的最前面,这时可以通过如下代码设置:

MyDialog myDlg; 
myDlg.setModal(false);
//或者
myDlg.setModal();   
myDlg.show();
//关键是下面这行
myDlg.setWindowFlags(Qt::WindowStaysOnTopHint);

在Qt中创建模态对话框,主要用到了QDialog的exec函数:

SonDialog dlg(this);

int res = dlg.exec();
if (res == QDialog::Accepted)
{
QMessageBox::information(this, “INFORMATION”, “You clicked OK button!);
}

if (res == QDialog::Rejected)
{
QMessageBox::information(this, “INFORMATION”, “You clicked CANCEL button!);
}

正如上面代码所显示的,可以通过exec函数的返回值来判断用户点击了哪个按钮使得模态对话框退出的,这可以使得我们能够根据用户的不同行为在退出模态对话框之后采取不同的处理方法。

既然new了,如果不delete,那么内存不就存在了泄露的问题了吗?确实如此!所以,我们希望该Qt窗口在退出时自动能够delete掉自己,因此,我们在SonDialog的构造函数里,添加这样的一句代码:

setAttribute (Qt::WA_DeleteOnClose);

这样,我们的SonDialog就能够在它退出时自动的delete掉自己了,不会再造成内存泄漏问题。

Qt中存在“窗口”与“部件”的区分,但“窗口”的概念太过浅显,以至于可以忽略不谈。但有时候还是多少有些了解为好。

很多书上说,Qt中吧没有嵌入到其他部件中的部件成为“窗口”,而这种“窗口”都包含有边框和标题栏。“窗口”就是没有父窗口(或部件)的部件,又称为顶级部件。但在实际开发过Qt程序的工程师看来,这种说法有点欠佳。“窗口是没有嵌入到其他部件的部件“这个好理解,但是“窗口”就是没有父部件的部件?QDialog为窗口是毋庸置疑的吧,但是在使用对话框时为其指定父窗口也是在正常不过了。例如,当我点击主窗口某个按钮时弹出个提示对话框:

QDialog dlg(this);

dlg.exec();

弹出的Dialog一样具有边框和标题栏,难道这种具有父部件的对话框就是不是窗口了?很多人难以接受吧! 所以,一个QWidget是窗体还是窗体上的控件和是否有父类无关,只与窗口标记类型有关,也只有窗口flag才能直接说明此部件是否为窗口!设置或修改部件类型:setWindowFlags(Qt::Window)

但是也无需怀疑很多书本的可靠性,其实书上说的也没错,只是不够深入。例如:

QPushButton * pPushBtn = new QPushButton(this);

//当没有父类时,构造函数就会加上Qt::Window标记

QPushButton * pPushBtn = new QPushButton;

因为,当没有指定父窗口(部件)时都是默认设置了Qt::Window标记的。再如:

//不管有无父类都为窗体,因为向QWidget传参数时传递了Qt::Dialog标记.

QDialog * dlg = new QDialog(this);

因此,QDialog是个独特的部件,无论有无指定父部件,其生来就是Window!

总而言之:所以使QWidget变成Window(窗体)只能使用setWindowFlags(Qt::Window); !!!在使用Qt是一般不考虑窗口的概念,较多情况下都直接使用QWidget就行了,对于自定义部件也是如此。对于之前做过VC的选手可能习惯了使用CDialog,但在Qt中QDialog却没那么受待见,熟练使用QWidget才是王道。

对于 QDialog 的模态及非模态是直接可以实现的,很多课本中都会提到,此处总结下。

模态QDialog

方式一:

QDialog dlg(this);
dlg.exec();

方式二:

QDialog *pDlg=new QDialog(this);
pDlg->setModal(true);
pDlg->show();

非模态QDialog

QDialog *pDlg=new QDialog(this);
pDlg->show();

QDialog实现模态非模态很简单,但是对于QWidget有点迷茫,QWidget中没有exec(),也没有setModal()方式,但是想想看,QWidget作为QDialog的基类,而且QWidget作为“窗口”使用也是在平常不过了,所以会意识到QWidget中是否存在一个相对exec()或setModal()更基本的操作来实现模态和非模态呢?就这样,我找到了setWindowModality(),此函数就是用来设置QWidget运行时的程序阻塞方式的,参数解释如下:

Qt::NonModal 不阻塞

Qt::WindowModal 阻塞父窗口,所有祖先窗口及其子窗口

Qt::ApplicationModal 阻塞整个应用程序

看来,setModal()也就是使用setWindowModality()设置Qt::ApplicationModal参数也实现的模态。

如此,要实现QWidget的模态和非模态,只要调用setWindowModality()设置阻塞类型就好了:

QWidget *pWid = new QWidget(this);
pWid->setWindowModality(Qt::ApplicationModal);
//pWid->setAttribute(Qt::WA_ShowModal, true);
pWid->show();

但是运行发现并未实现模态效果。这里需要注意,当希望使用setWindowModality()将QWidget设置为模态时应该保证QWidget父部件为0,这里修改

QWidget *pWid = new QWidget(this); 

QWidget *pWid = new QWidget(NULL);

在运行就好了。

此外,通过setWindowModality()设置模态窗口并不是唯一方式,直接设置部件(或窗口)属性也可以:

pWid->setAttribute(Qt::WA_ShowModal, true)

还有很多地方需要注意,当创建QDialog后使用setWindowFlags(Qt::FramelessWindowHint);去掉标题栏时此对话框不再阻塞父窗口,如果需要实现阻塞效果可再次指定Qt::Dialog,即使用:

setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint); //这样就会阻塞父窗口了!

但是,这样会影响对话框的半透明(或透明)显示。使用Qt::Dialog之前半透明显示正常:

使用之后却死活不行了:

– 不知道如何是好!


总而言之

是否是模态和QDialog 和QWidget都可以模态和非模态.exec(), show() 等函数无直接关系,只和窗口属性有关,使用以下两种方式都行:

setAttribute(Qt::WA_ShowModal, true);//属性设置
setWindowModality(Qt::ApplicationModal);//设置阻塞类型

QDialog中的成员函数setModal(true)及exec()之所以是模态是因为他先设置了窗口属性:setAttribute()再show()的

模态对话框:指该对话框关闭之前不可以对其他窗口进行操作,只有等该对话框关闭之后才可以操作其他窗口。
非模态对话框:该对话框激活的情况下也可以对其他窗口进行操作。

模态对话框:

Qdialog dlg;
dlg.show();

执行上面的代码,我们会发现窗口一闪而过,其原因是因为dlg被申明为一个局部变量,当用完之后就自动销毁,所以窗口show完之后立马就被释放。为了不让它一闪而过,使用
dlg.exec();//阻塞
这个语句起到阻塞程序的作用,当执行到这里的时候停住了,这样也不能对其他窗口进行操作,所以

Qdialog dlg;
dlg.exec();

就是模态对话框的写法。

非模态对话框:

Qdialog *dlg=new Qdialog;
dlg->show();
dlg->setAttribute(Qt::WA_DelecteOnClose);

执行上面程序弹出窗口不会一闪而过,因为new创建在堆上,不会自动销毁,需要手动delete。dlg->setAttribute(Qt::WA_DelecteOnClose)的作用是当窗口关闭时,对话框释放。

模态对话框:非阻塞

 //方法1
TestDialog childWindow ;
childWindow.setModal(false);
//childWindow.show();//不可行
childWindow.exec();//可行
//方法2
TestDialog * childWindow = new TestDialog();
childWindow->setModal(false);
childWindow->show();

在子窗口初始化中加入

setAttribute (Qt::WA_DeleteOnClose); //防止内存泄漏。

防止内存泄漏。

非模态对话框:阻塞

//方法1
TestDialog * childWindow = new TestDialog();
childWindow->setModal(true);
childWindow->show();
//方法2

TestDialog* childWindow = new TestDialog();
childWindow->setWindowModality(Qt::WindowModal);
childWindow->show();

qDialog的setmodal,对话框模态、非模态
对话框模态,关闭当前对话框前,无法操作其他窗口

非模态,当前对话框打开同时,也可以操作其他对话框

模态在对话框创建时设定好后,程序运行过程中无法切换!(如:对话框A当前为非模态,弹出后,设置为模态,不起作用)

1.如果使用exec()默认为模态的。如果用show()需要设置setModel(true)才是模态的。

方法1:模态窗口

A为窗口类, 父类窗口为B

A *dlg = new A(this,pB); //(可确保A显示在B之上)

dlg->exe()

注意:此时使用setModal无效果

方法2:

A *dlg = new A(this,pB); //(可确保A显示在B之上)

dlg-.setModel(true);
dlg->show()

2、close()会销毁对象嘛。只有当设置了 setAttribute(WA:closeOnDelelte)是才会删除,如果这个标志没有设置,其作用和hide(),setvisible(false)一样,只会隐藏改对象。

A为窗口类, 父类窗口为B

A *dlg = new A(this,pB); //(可确保A显示在B之上)

dlg->setAttribute(WA:closeOnDelelte);
dlg->show;

注意,此时需要使用close();否则dlg指针未被管理。

3、QWidget的模态和非模态;

4、阻塞?

QDialog模态对话框与非模态对话框 范例

//模态1
MyWidget*w = new MyWidget; //派生于QWidget

w->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
w->setAttribute(Qt::WA_ShowModal, true);
w->setAttribute(Qt::WA_DeleteOnClose, true);
w->show();

//模态2

MyDialog _dialog; //派生于QDialog

int ret = _dialog.exec();
if (ret == QDialog::Accepted)
{

} 

//模态附加
void on__btnSave_clicked()
{
this->accept();
this->close();
}

if (res == QDialog::Accepted)

//非模态
MyDialog* _pMyDialog = new MyDialog ;

_pMyDialog->setAttribute(Qt::WA_DeleteOnClose);
_pMyDialog->setModal(false);
_pMyDialog->show();

[2] Qt工作笔记-主界面往模式对话框emit信号,有注意的问题

原文链接

今天遇到个坑,往主界面往模式对话框emit信号。
应为模式对话框exec后,主界面就不响应了,emit也发不了。所以要先emit,再exec。

运行截图如下:

正常情况下:

在这里插入图片描述
此时,相关代码如下:

void Widget::openBtnClicked(){
    m_dialog=new Dialog();
    connect(this,SIGNAL(btnClicked(QString)),m_dialog,SLOT(receive(QString)));
    emit btnClicked(ui->lineEdit->text());
    m_dialog->exec();
}

不正常情况下:

在这里插入图片描述
代码如下:

void Widget::openBtnClicked(){
    m_dialog=new Dialog();
    connect(this,SIGNAL(btnClicked(QString)),m_dialog,SLOT(receive(QString)));
    m_dialog->exec();
    emit btnClicked(ui->lineEdit->text());
}

下面给出正常情况下的代码:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
 
namespace Ui {
class Dialog;
}
 
class Dialog : public QDialog
{
    Q_OBJECT
 
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
public slots:
    void receive(QString msg);
 
private:
    Ui::Dialog *ui;
};
 
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
 
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}
 
void Dialog::receive(QString msg){
    ui->lineEdit->setText(msg);
}
 
Dialog::~Dialog()
{
    delete ui;
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include "dialog.h"
 
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
public slots:
    void openBtnClicked();
 
signals:
    void btnClicked(QString msg);
 
private:
    Ui::Widget *ui;
    Dialog *m_dialog;
 
};
 
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(openBtnClicked()));
}
 
void Widget::openBtnClicked(){
    m_dialog=new Dialog();
    connect(this,SIGNAL(btnClicked(QString)),m_dialog,SLOT(receive(QString)));
    emit btnClicked(ui->lineEdit->text());
    m_dialog->exec();
}
 
Widget::~Widget()
{
    delete ui;
}

main.cpp

#include "widget.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
    return a.exec();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512323.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KVM软件安装/Guest OS图形模式安装

KVM软件安装 首先你的Linux操作系统得带有图形化界面 虚拟机开启硬件虚拟化 关闭防火墙和selinux [rootserver-d ~]# systemctl stop firewalld [rootserver-d ~]# systemctl disable firewalld Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.ser…

RK3568修改调试串口的波特率

概述 使用了临滴 RK3568 开发板,其调试串口的默认波特率是 1500000 &#xff0c;但并不是所有的 USB 转 TTL 都能使用这么高的波特率&#xff0c;所以我们就将波特率修改为 115200 这个比较通用的波特率。 RK3568 调试串口修改波特率的方法 ddr 运行阶段串口波特率的修改 ddr…

linux利用定时任务提权

背景&#xff1a; 运维为了防止数据丢失等&#xff0c;写个定时任务进行数据的打包压缩。由于数据打包压缩命令为tar&#xff0c;tar可以尝试加参数调用其他命令执行。 压缩命令&#xff1a;tar zxf 1.tar.gz /var/www/* 查看定时任务&#xff1a;cat /etc/crontab root权限下…

WordPress入门之WordPress站点基本设置

在Wordpress站点搭建过程中,我们需要快速去熟悉Wordpress,并进行一些简单的基本设置,在开始设置之前,大家可以先熟悉左边的菜单栏的每个选项,了解它们都是做什么的,今天就简单为大家介绍Wordpress入门之Wordpress站点基本设置。 一、设置个人资料 建议大家完善基本信息…

电容笔一定要防误触吗?苹果平板平替电容笔排行

至于用ipad作为学习工具的学生们&#xff0c;更是将它当成了一种必不可少的工具。但是&#xff0c;由于苹果原装电容笔的价格过高&#xff0c;没有人能负担得起。所以&#xff0c;最好的办法就是使用普通的电容笔。我是IPAD的忠实用户&#xff0c;也是数码爱好者&#xff0c;这…

10.BOM浏览器对象模型

BOM 浏览器对象模型 1. BOM 概述 1.1 什么是 BOM BOM&#xff08;Browser Object Model&#xff09;即浏览器对象模型&#xff0c;它提供了独立于内容而与**浏览器窗口进行交互的对象&#xff0c;其核心对象是 window BOM 由一系列相关的对象构成&#xff0c;并且每个对象都…

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

作者&#xff1a;京东零售 吴滔 本教程将使用北汽登录模块为例&#xff0c;一步一步和大家一起搭建单元测试用例&#xff0c;并在Bamboo上跑起来&#xff0c;最终测试结果和代码覆盖率会Bamboo上汇总。 模块名称&#xff1a;BQLoginModule,是通过iBiu创建的一个模块工程 一 建…

浅尝Kubernetes

第一节 内容编排与Kubernetes 为什么要用k8s 集群环境容器部署的困境&#xff0c;假设我们有数十台服务器。分别部署Nginx&#xff0c;redis&#xff0c;mysql&#xff0c;业务服务。如何合理的分配这些资源。这里就需要用到容器编排 容器编排 在实际集群环境下&#xff0…

JAVA-抽象类和接口

文章目录 前言 大家好呀,今天给大家带来抽象类和接口的讲解,那么废话不多说,跟着我一起去学习吧! 1.1抽象类的概念 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果 一个类…

Java 11新特性:模块化系统和本地变量类型推断

作为Java语言的最新版本&#xff0c;Java 11带来了许多新特性&#xff0c;其中最引人注目的是模块化系统和本地变量类型推断。这两个新特性对Java开发人员来说具有重要意义&#xff0c;因此在本文中&#xff0c;我们将详细探讨这两个新特性及其对Java开发的影响。 章节1&#…

记录一次uniapp实现APP自动升级

描述 app的版本管理和升级&#xff0c;是一个不可或缺的功能&#xff0c;而uniapp则是提供了一整套的流程&#xff0c;由于官方文档过于复杂&#xff0c;而且写的云里雾里的&#xff0c;所以个人记录一次我的操作&#xff0c;直到配置成功。 总体 一共分为2个部分&#xff0…

scanf与printf函数的用法

前言&#xff1a; 学习c语言编程&#xff0c;必不可少的操作就是键盘输入与屏幕输出。今天我想讲讲自己对scanf与printf使用的看法 一、scanf与printf&#xff1a; 1.scanf()函数&#xff1a; int scanf ( const char * format, ... ); 函数的功能&#xff1a;从标准输入中…

契约锁亮相华为2023中国合作伙伴大会,共谱华为云软件生态新篇章

5月8日-9日&#xff0c;以“因聚而生 众志有为”为主题的“华为中国合作伙伴大会2023”在深圳举行。契约锁作为华为云优秀软件伙伴&#xff0c;受邀参会并在“聚数字化先行者&#xff0c;谱软件生态新乐章”分论坛开展“让数字可信&#xff0c;打通数字化最后一公里”数字化实践…

Google Play 政策更新重点回顾 (下) | 2023 年 4 月

Google Play 和您一样&#xff0c;始终坚持为用户提供更优质的产品、更流畅的体验。为持续打造值得信赖的优质应用平台&#xff0c;我们也在不断进行政策更新。在上一篇文章中与您回顾了 2023 年 4 月 Google Play 政策的更新要点&#xff0c;这篇文章我们将为您带来重点政策解…

golang汇编之常量和全局变量(三)

常量 Go汇编语言中常量以$美元符号为前缀。常量的类型有整数常量、浮点数常量、字符常量和字符串常量等几种类型。以下是几种类型常量的例子&#xff1a; $1 // 十进制 $0xf4f8fcff // 十六进制 $1.5 // 浮点数 $a // 字符 $"abcd" …

【加解密篇】Passware Kit Forensic暴力美学-已知部分密码自定义解密详细参数设置

【加解密篇】Passware Kit Forensic暴力美学-已知部分密码自定义解密详细参数设置 都说"自制武器不一定是最强的&#xff0c;但最强的武器一定是自制的"&#xff0c;对于取证工具也是一样&#xff0c;虽然默认配置足够强&#xff0c;但如果我们能根据实时情景自定义…

arduino 导入 Brain 库

一、引言 最近在做一个可以用脑电波控制的arduino小车&#xff0c;需要用到Brain这个库&#xff0c;而且需要自己导入才能使用。之前试了很多方法&#xff0c;导入成功了&#xff0c;过了几个月又忘记怎么导入了&#xff0c;今天想起来记录一下&#xff0c;好记性不如烂笔头。 …

LNK2019 无法解析的外部符号,一种新的思路

LNK2019 无法解析的外部符号&#xff0c;一种新的思路 一般来说&#xff0c;这种问题的原因有如下几点&#xff1a; 函数只有声明没有实现如果是其它库的函数&#xff0c;可能没有链接lib文件如果函数是封装在dll中的&#xff0c;可能没有导出如果是模板函数或模板类&#xf…

初始MyBatis,w字带你解MyBatis

一.什么是mybatis mybatis的概念 MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。1、Mybatis是一个半ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;底层封装了JDBC&#xff0c;是程序员在开发时只需要关注SQL语句本身&#…

U-boot顶层Makefile文件分析(一)

在阅读 uboot 源码之前&#xff0c;肯定是要先看一下顶层 Makefile&#xff0c;分析 gcc 版本代码的时候一定是先从顶层 Makefile 开始的&#xff0c;然后再是子 Makefile&#xff0c;这样通过层层分析 Makefile 即可了解整个工程的组织结构。顶层 Makefile 也就是 uboot 根目录…