对话框:用于提示用户输入
对话框分为两种:
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()进行断言,至少不会在很久很久以后坑自己