对话框:用于提示用户输入

对话框分为两种:

1、模式对话框Modal

背景界面卡住,用户必须在完成对话框输入并关闭对话框之后,才能回到背景界面

2、非模式对话框Non-Modal

背景界面可以活动,这篇博客将分别介绍

一、模式对话框Modal

新建对话框

小练习:点击登陆按钮,弹出对话框提示用户要输入信息才能登陆,用户点击确认或取消,回到主界面。

要求:

1、新建对话框,布局

2、点确定时,accept()对话框返回; 点取消时,reject()对话框返回

3、运行对话框exec(),注意exec的返回值

4、取得用户输入

步骤:

1、需要定义一个新的GUI类,继承自QDialog

添加完,在Qt Disigner中会发现多了一个窗体,对它进行布局。

2、在主窗体中 包含 刚刚添加的头文件,在事件中创建对象,并执行exec()方法。

3、在LoginDlg窗体中添加事件,及响应的处理,代码如下:

Test7_1a_12_7::Test7_1a_12_7(QWidget *parent)	: QMainWindow(parent){	ui.setupUi(this);	assert(		connect(			ui.btnLogin,			SIGNAL(clicked()),			this,			SLOT(OnBtnLogin())			)		);}int Test7_1a_12_7::OnBtnLogin(){	//创建对话框	LoginDlg dlg(this);	//这个地方,如果传参不指定父类,则该窗口时独立的,若 指定,则需要处理完该窗口,才可以操作父类	int ret = dlg.exec();	//对话框显示,程序阻塞	//判断子窗口的运行结果	if (ret == QDialog::Accepted)	{		QMessageBox::information(this, "success", "success");	}	else if(ret == -1) 	{		QMessageBox::information(this, "wrong", "wrong");	}	return 0;}///LoginDlg::LoginDlg(QWidget *parent)	: QDialog(parent){	ui.setupUi(this);	assert(		connect(			ui.btnEnter,			SIGNAL(clicked()),			this,			SLOT(OnBtnEnter())			)		);	assert(		connect(			ui.btnCancel,			SIGNAL(clicked()),			this,			SLOT(OnBtnCancel())			)		);}LoginDlg::~LoginDlg(){}int LoginDlg::OnBtnEnter(){	if (ui.lineEditName->text() == "admin" && ui.lineEditPswd->text() == "123456")	{		accept();	//表示成功	}	reject();	//表示密码错误}int LoginDlg::OnBtnCancel(){	return -1;	//取消}

二、文件对话框

Qt中有一个QFileDialog类

//打开文件:static QString QFileDialog::getOpenFileName//保存文件:static QString QFileDialog::getSaveFileName

这两个static函数,返回值均为被选择的文件名

举例:

打开一个文本文档,并显示

Test7_2b_12_7::Test7_2b_12_7(QWidget *parent)	: QMainWindow(parent){	ui.setupUi(this);	assert(		connect(			ui.btnOpen,			SIGNAL(clicked()),			this,			SLOT(OnBtnOpen())			)		);	assert(		connect(			ui.btnSave,			SIGNAL(clicked()),			this,			SLOT(OnBtnSave())			)		);}QString Test7_2b_12_7::OnBtnOpen(){	QString FilePath;	while (FilePath.length() <= 0)	{		FilePath = QFileDialog::getOpenFileName(this, AfGbk::ToUnicode("打开"));	}	return FilePath;}QString Test7_2b_12_7::OnBtnSave(){	QString FilePath = QFileDialog::getOpenFileName(this, AfGbk::ToUnicode("保存"));	return FilePath;}

再做一个小练习,实现一个简单的文本编辑器,允许打开文档并进行修改和保存

打开:

QString Test7_2b_12_7::OnBtnOpen(){	QString FilePath;	while (FilePath.length() <= 0)	{		FilePath = QFileDialog::getOpenFileName(this, AfGbk::ToUnicode("打开"));		assert(FilePath != NULL);		std::string gbk_name = AfGbk::FromUnicode(FilePath);		//打开文件,读取内容		FILE* fp = fopen(gbk_name.c_str(), "rb");		//获取文件的大小		fseek(fp, 0, SEEK_END);		int FileSize = ftell(fp);		//读取文件内容		fseek(fp, 0, SEEK_SET);		char* buf = new char[FileSize+1];	//注意回收		int n = fread(buf, 1, FileSize, fp);		if ( n > 0 )		{			buf[n] = 0;			ui.plainTextEdit->setPlainText(AfGbk::ToUnicode(buf));		}		fclose(fp);		delete[] buf;	}	return FilePath;}

保存:

QString Test7_2b_12_7::OnBtnSave(){	QString FilePath;	while (FilePath.length() <= 0)	{		FilePath = QFileDialog::getSaveFileName(this, AfGbk::ToUnicode("选择保存路径"));		std::string gbk_name = AfGbk::FromUnicode(FilePath);		assert(FilePath != NULL);		std::string gbk_text = AfGbk::FromUnicode(ui.plainTextEdit->toPlainText());		//要写入的内容		//打开文件,写入内容		FILE* fp = fopen(gbk_name.c_str(), "wb");		fwrite(gbk_text.c_str(), 1, gbk_text.length(), fp);		fclose(fp);	}	return FilePath;}

注意:各个程序的文件对话框界面都是一样的。

文件对话框的特殊性:它不是普通的对话框,这个对话框本质上是由系统函数提供的

三、优化Qt项目的目录结构

Qt中有一个QFileDialog类

1、改变程序的输出位置

程序默认输出到Debug目录下

一般是把程序输出到指定位置,可以在“项目属性/链接器”里面设置

2、代码放在文件夹里

将*.c *.h *.ui 放在src目录下,使整个项目的目录更整洁,容易维护

3、指定进程的当前目录

我们希望进程的当前目录就是 *.exe的路径

四、非模态窗口 (Non-Modal)

Qt中有一个QFileDialog类

模态窗口(Modal):

只有前台窗口可以接收输入,后台被阻塞

非模态窗口(Non-Modal):

前台、后台均可接受输入

非模式窗口的使用:

添加一个Widget类

创建一个Widget对象,作为成员变量

在用户执行搜索菜单的时候显示此窗口

当用户在窗口内有动作时,响应该动作

和对话框的区别:父类不同,这里继承自窗口Qwidget类,而对话框则继承自QDialog类

————————————————————————

尾巴:

在打开、关闭时,一定要考虑到这个字符串为空的情况,并进行处理

如果在开发过程中实在懒得写,至少也一定要用assert()进行断言,至少不会在很久很久以后坑自己