自定义的对话框

对话框的显示分模态对话框和非模态对话框。

创建对话框

1.创建对话框

单击Qt Creator的菜单项“File”→“New File or Project”,选择Qt类别下的“Qt Designer Form Class”,创建可视化设计的对话框类。在随后出现的向导里,选择窗口模板为Dialog without Buttons,并设置自定义对话框的类名。

会得到3个文件,分别为.h ,.c,ui文件。
设置好自己的对话框界面。

2.对话框的调用和返回值

设计QWDialogSize对话框的界面时,在上面放置了两个QPushButton按钮,并分别命名为btnOK和btnCancel,分别是“确定”和“取消”按钮,用于获取对话框运行时用户的选择。

在信号与槽编辑器里,将btnOK的clicked()信号与对话框的accept()槽关联,将btnCancel的clicked()信号与对话框的reject()槽关联即可,如图所示:

单击“确定”按钮会执行accept()槽(或在代码里调用accept()槽函数也是一样的),这会关闭对话框(默认情况下,对话框只是被隐藏,并不被删除),并返回QDialog::Accepted 作为exec()函数的返回值。

单击“取消”按钮会执行reject()槽函数,也会关闭对话框,并返回QDialog::Rejected作为exec()函数的返回值。

注意的是:
我们的主界面是没有办法去访问到我们的对话框上面的组件的信息的,所以我们必须通过对外的接口函数把数据传输出去,就是我们要提供公共的接口把,ui界面的数据给传输给主界面。或者是我们在对话框的构造函数的时候,把一个结构体的指针传入进来,接收数据信息。

1.创建一个模态对话框,并把数据给到主界面,并及时释放掉

void MainWindow::on_actTab_SetSize_triggered()
{ //模态对话框,动态创建,用过后删除QWDialogSize   *dlgTableSize=new QWDialogSize(this); Qt::WindowFlags   flags=dlgTableSize->windowFlags();dlgTableSize->setWindowFlags(flags | Qt::MSWindowsFixedSizeDialogHint); dlgTableSize->setRowColumn(theModel->rowCount(),theModel->columnCount()); int ret=dlgTableSize->exec();// 以模态方式显示对话框,if (ret==QDialog::Accepted)  { //OK按钮被按下,获取对话框上的输入,设置行数和列数int cols=dlgTableSize->columnCount();theModel->setColumnCount(cols);int rows=dlgTableSize->rowCount();theModel->setRowCount(rows);}delete dlgTableSize;
}
Qt::WindowFlags:
Qt::Widget               //是一个窗口或部件,有父窗口就是部件,没有就是窗口
Qt::Window               //是一个窗口,有窗口边框和标题
Qt::Dialog               //是一个对话框窗口
Qt::Sheet                //是一个窗口或部件Macintosh表单
Qt::Drawer               //是一个窗口或部件Macintosh抽屉,去掉窗口左上角的图标
Qt::Popup                //是一个弹出式顶层窗口
Qt::Tool                 //是一个工具窗口
Qt::ToolTip              //是一个提示窗口,没有标题栏和窗口边框
Qt::SplashScreen         //是一个欢迎窗口,是QSplashScreen构造函数的默认值
Qt::Desktop              //是一个桌面窗口或部件
Qt::SubWindow            //是一个子窗口

//为窗口添加一些功能,窗口属性:

Qt::CustomizeWindowHint          //关闭默认窗口标题提示
Qt::WindowTitleHint              //为窗口修饰一个标题栏
Qt::WindowSystemMenuHint         //为窗口修饰一个窗口菜单系统
Qt::WindowMinimizeButtonHint     //为窗口添加最小化按钮
Qt::WindowMaximizeButtonHint     //为窗口添加最大化按钮
Qt::WindowMinMaxButtonsHint      //为窗口添加最大化和最小化按钮
Qt::WindowCloseButtonHint           //窗口只有一个关闭按钮
Qt::WindowContextHelpButtonHint
Qt::MacWindowToolBarButtonHint
Qt::WindowFullscreenButtonHint
Qt::BypassGraphicsProxyWidget
Qt::WindowShadeButtonHint
Qt::WindowStaysOnTopHint    //总在最上面的窗口,置前
Qt::WindowStaysOnBottomHint
Qt::WindowOkButtonHint
Qt::WindowCancelButtonHint
Qt::WindowTransparentForInput

增加

this->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);

去除

setWindowFlags(windowFlags()& ~Qt::WindowMaximizeButtonHint);//去掉最大化按钮

从代码中可以看到,每次单击此工具栏按钮时,对话框都被重新创建。创建后用QDialog的setWindowFlags()函数将对话框设置为固定大小,然后调用对话框的自定义函数setRowColumn(),将主窗口数据模型theModel的现有的行数和列数显示到对话框上的两个SpinBox组件里。

调用对话框的exec()函数,以模态显示的方式显示对话框。模态显示方式下,用户只能在对话框上操作,不能操作主窗口,主程序也在此处等待exec()函数的返回结果。

当用户单击“确定”按钮关闭对话框后,exec()返回结果为QDialog::Accepted,主程序获得此返回结果后,通过对话框的自定义函数columnCount()和rowCount()获得对话框上新输入的列数和行数,然后设置为数据模型的列数和行数。

最后使用delete删除创建的对话框对象,释放内存。所以,关闭对话框时,会出现QWDialogSize析构函数里的消息提示对话框。

注意:
在对话框上单击按钮或关闭对话框时,对话框只是隐藏(缺省的),而并没有从内存中删除。如果对话框一关闭就自动删除,则在后面调用对话框的自定义函数获得输入的行数和列数时会出现严重错误。所以,我们需要拿到自己想的数据之后再进行delete。

2.创建模态对话框的一次创建,多次使用,存储对话框的指针

void MainWindow::on_actTab_SetHeader_triggered()
{//一次创建,多次调用,对话框关闭时只是隐藏if (dlgSetHeaders==NULL) dlgSetHeaders = new QWDialogHeaders(this);if (dlgSetHeaders->headerList().count()!=theModel->columnCount()){//如果表头列数变化,重新初始化QStringList strList;for (int i=0;i<theModel->columnCount();i++)//获取现有的表头标题strList.append(theModel->headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());dlgSetHeaders->setHeaderList(strList);//对话框初始化显示}int ret=dlgSetHeaders->exec();// 以模态方式显示对话框if (ret==QDialog::Accepted) //OK键被按下{QStringList strList=dlgSetHeaders->headerList();theModel->setHorizontalHeaderLabels(strList);// 设置模型的表头标题}
}

3.非模态对话框,关闭的时候自动删除

void MainWindow::on_actTab_Locate_triggered()
{//创建 StayOnTop的对话框,对话框关闭时自动删除ui->actTab_Locate->setEnabled(false); dlgLocate = new QWDialogLocate(this);dlgLocate->setAttribute(Qt::WA_DeleteOnClose); //对话框关闭时自动删除Qt::WindowFlags   flags=dlgLocate->windowFlags(); //获取已有flagsdlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint); //StayOnTopdlgLocate->setSpinRange(theModel->rowCount(),theModel->columnCount());QModelIndex curIndex=theSelection->currentIndex();if (curIndex.isValid())dlgLocate->setSpinValue(curIndex.row(),curIndex.column());dlgLocate->show();  //非模态显示对话框
}

4.对话框中操作主窗口

示例代码:

void QWDialogLocate::on_btnSetText_clicked()
{//定位到单元格,并设置字符串int row=ui->spinBoxRow->value(); //行号int col=ui->spinBoxColumn->value();//列号MainWindow *parWind = (MainWindow*)parentWidget(); //获取主窗口parWind->setACellText(row,col,ui->edtCaption->text()); //调用主窗口函数if (ui->chkBoxRow->isChecked()) //行增ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());if (ui->chkBoxColumn->isChecked()) //列增ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
}

想要在对话框中操作主窗口,就需要获取主窗口对象,调用主窗口的函数并传递参数。在上面的代码中,通过下面一行语句获得主窗口对象:

MainWindow *parWind = (MainWindow*)parentWidget();

parentWidget()是QWidget类的一个函数,指向父窗口。在创建此对话框时,将主窗口的指针传递给对话框的构造函数,即:

dlgLocate = new QWDialogLocate(this);

所以,对话框的parentWidget指向主窗口。

然后调用主窗口的一个自定义的public函数setACellText(),传递行号、列号和字符串,由主窗口更新指定单元格的文字。下面是主窗口的setACellText()函数的代码。

void MainWindow::setACellText(int row, int column, QString text)
{//定位到单元格,并设置字符串QModelIndex index=theModel->index(row,column);//获取模型索引theSelection->clearSelection();theSelection->setCurrentIndex(index,QItemSelectionModel::Select); theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
}

这样就实现了在对话框里对主窗口进行的操作,主要是获取主窗口对象,然后调用相应的函数。

5.主窗口中操作对话框

因为父窗口中创建了对话框,是可以知道对话框的指针的,可以之间对对话框的指针进行操作就可以了。

示例代码如下:

void MainWindow::on_tableView_clicked(const QModelIndex &index)
{//单击单元格时,将单元格的行号、列号设置到对话框上if (dlgLocate!=NULL) dlgLocate->setSpinValue(index.row(),index.column());
}

因为主窗口中定义了对话框的指针,只要它不为NULL,就说明对话框存在,调用对话框的一个自定义函数setSpinValue(),刷新对话框显示界面。QWDialogLocate的setSpinValue()函数实现如下:

void QWDialogLocate::setSpinValue(int rowNo, int colNo)
{//设置SpinBox组件的数值ui->spinBoxRow->setValue(rowNo);ui->spinBoxColumn->setValue(colNo);
}

6.窗口的CloseEvent事件

对话框和主窗口之间互相操作的关键是要有对方对象的指针,然后才能传递参数并调用对方的函数。

由于对话框是以非模态方式运行的,程序无法等待对话框结束后作出响应,但是可以利用窗口的CloseEvent事件。

事件(event)是由窗口系统产生的由某些操作触发的特殊函数,例如鼠标操作、键盘操作的一些事件,还有窗口显示、关闭、绘制等相关的事件。从QWidget继承的窗口部件常用的事件函数有如下几种。

closeEvent():窗口关闭时触发的事件,通常在此事件做窗口关闭时的一些处理,例如显示一个对话框询问是否关闭窗口。
showEvent():窗口显示时触发的事件。
paintEvent():窗口绘制事件。
mouseMoveEvent():鼠标移动事件。
mousePressEvent():鼠标键按下事件。
mouseReleaseEvent():鼠标键释放事件。
keyPressEvent():键盘按键按下事件。
keyReleaseEvent():键盘按键释放事件。

要利用对话框的closeEvent()事件,在类定义中声明了此事件的函数,其实现代码如下:

void QWDialogLocate::closeEvent(QCloseEvent *event)
{ //窗口关闭 eventMainWindow *parWind = (MainWindow*)parentWidget(); //获取父窗口指针parWind->setActLocateEnable(true);//使能 actTab_LocateparWind->setDlgLocateNull(); //将窗口指针设置为NULL
}

利用closeEvent()事件,可以询问窗口是否退出,例如为主窗口添加closeEvent()事件的处理,代码如下:

void MainWindow::closeEvent(QCloseEvent *event)
{ //窗口关闭时询问是否退出QMessageBox::StandardButton result=QMessageBox::question(this,"确认", "确定要退出本程序吗?",QMessageBox::Yes|QMessageBox::No |QMessageBox::Cancel,QMessageBox::No);if (result==QMessageBox::Yes)event->accept();elseevent->ignore();
}

这样,主窗口关闭时就会出现一个询问对话框,如果不单击“Yes”按钮,程序就不关闭;否则应用程序结束。

改进主窗口与对话框之间的交互

前面都是直接利用操作对应的指针,然后调用函数来进行操作主窗口或者对话框,比较的麻烦,而却直接操作指针不大好。可以利用信号与槽来改进。

如我们的主窗口为MainWindow,对话框为QWDialog采用信号与槽机制实现交互操作。

MainWindow类的定义的信号与处理函数:

class MainWindow : public QMainWindow
{//信号处理函数
public slots:void   setACellText(int row, int column, QString &text);//设置单元格内容void   setActLocateEnable(bool enable);//设置actTab_Locate的enabled属性
//信号
signals:void   cellIndexChanged(int rowNo, int colNo);//当前单元格发生变化...
};

MainWindow对应函数的代码:

void MainWindow::setACellText(int row, int column, QString &text)
{//定位到单元格,并设置字符串QModelIndex index=theModel->index(row,column);//获取模型索引theSelection->clearSelection();theSelection->setCurrentIndex(index,QItemSelectionModel::Select); theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
}
void MainWindow::setActLocateEnable(bool enable)
{ //设置actTab_Locate的enabled属性ui->actTab_Locate->setEnabled(enable);
}
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{//单击单元格时发射信号,传递单元格的行号、列号emit cellIndexChanged(index.row(),index.column());
}

当点击对应的创建对话框按键时代码:

void MainWindow::on_actTab_Locate_triggered()
{//创建 StayOnTop的对话框,对话框关闭时自动删除QWDialogLocate *dlgLocate = new QWDialogLocate(this); dlgLocate->setAttribute(Qt::WA_DeleteOnClose); Qt::WindowFlags   flags=dlgLocate->windowFlags(); dlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint); dlgLocate->setSpinRange(theModel->rowCount(),theModel->columnCount());QModelIndex curIndex=theSelection->currentIndex();if (curIndex.isValid())dlgLocate->setSpinValue(curIndex.row(),curIndex.column());
//对话框发射信号,设置单元格文字connect(dlgLocate,SIGNAL(changeCellText(int,int,QString&)),this,SLOT(setACellText(int,int,QString&)));
//对话框发射信号,设置actTab_Locate的属性connect(dlgLocate,SIGNAL(changeActionEnable(bool)),this,SLOT(setActLocateEnable(bool)));
//主窗口发射信号,修改对话框上的spinBox的值   connect(this,SIGNAL(cellIndexChanged(int,int)),dlgLocate,SLOT(setSpinValue(int,int)));dlgLocate->show(); //非模态显示对话框
}

QWDialog类定义中,与信号和槽相关的定义如下:

class QWDialog: public QDialog
{private:void   closeEvent(QCloseEvent *event);void   showEvent(QShowEvent *event);
//处理函数
private slots:void   on_btnSetText_clicked();
public slots:void   setSpinValue(int rowNo, int colNo);
//信号
signals:void   changeCellText(int row, int column, QString &text);void   changeActionEnable(bool en);
};

对应的函数:

void QWDialogLocate::closeEvent(QCloseEvent *event)
{ //窗口关闭事件, 发射信号使 actTab_Locate 能用emit changeActionEnable(true);
}
void QWDialogLocate::showEvent(QShowEvent *event)
{//窗口显示事件, 发射信号使 actTab_Locate 不能用emit changeActionEnable(false);
}
void QWDialogLocate::setSpinValue(int rowNo, int colNo)
{//响应主窗口信号,更新spinBox的值ui->spinBoxRow->setValue(rowNo);ui->spinBoxColumn->setValue(colNo);
}
void QWDialogLocate::on_btnSetText_clicked()
{//发射信号,定位到单元格并设置字符串int row=ui->spinBoxRow->value(); //行号int col=ui->spinBoxColumn->value();//列号QString text=ui->edtCaption->text();//文字emit changeCellText(row,col,text);//发射信号if (ui->chkBoxRow->isChecked()) //行增ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());if (ui->chkBoxColumn->isChecked()) //列增ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
}

经过这样修改后的程序,能实现与前面的实例完全相同的主窗口与对话框交互的功能,但是与前面互相引用的方式不同,这里使用Qt的信号与槽的机制,无须获取对方的指针,程序结构上更简单一些。

Qt的对话框与窗口--自定义的对话框相关推荐

  1. Qt的对话框与窗口--标准的对话框

    Qt的对话框与窗口--标准的对话框 标准的对话框 QFileDialog对话框 1.选择打开一个文件 2.选择打开多个文件 3.选择已有目录 4.选择保存文件名 QColorDialog对话框 QFo ...

  2. android自定义dialog对话框,android的自定义dialog对话框实现

    Android自定义dialog对话框 一:自定义dialog 如何填充布局 ①自定MyDialog类,在类里关联布局 public class MyDialog extends AlertDialo ...

  3. Qt的对话框与窗口--Splash与登录窗口

    Splash与登录窗口 1 实例功能概述 一般的大型应用程序在启动时会显示一个启动画面,即Splash窗口.Splash窗口是一个无边对话框,一般显示一个图片,展示软件的信息.Splash窗口显示时, ...

  4. Qt的对话框与窗口--Qt中主要的窗体类及其用途

    Qt中主要的窗体类及其用途     常用的窗体基类是QWidget.QDialog和QMainWindow,在创建GUI应用程序时选择窗体基类就是从这3个类中选择.QWidget直接继承于QObjec ...

  5. python 如何做密码对话框_Python GUI教程(八):在主窗口中调用对话框

    本篇将会介绍: 使用qt设计师创建两个窗口 转换设计师UI代码为Python代码 从主窗口中调用对话框窗口 一.创建两个窗口 根据本篇的最终目标--在主窗口中调用对话窗口,我们先使用qt设计师创建两个 ...

  6. 【Qt教程】1.11 - Qt5 标准对话框QMessageBox(关于、错误、信息、警告、问题、颜色、字体、文件对话框)

    所谓标准对话框,是Qt内置的一些列对话框,用于简化开发.其实是调用的系统窗口.事实上,有很多对话框都是通用的,比如打开文件.设置颜色.打印设置等.这些对话框在素有程序中几乎相同,因此没有必要在每一个程 ...

  7. Android 自定义AlertDialog对话框

    2019独角兽企业重金招聘Python工程师标准>>> 系统默认的AlertDialog,与项目的UI不统一,所以,改了一下,定义了一样式,最终效果如下图: 另外,为了尽量少改原来的 ...

  8. Qt下的模态和非模态对话框

    模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在.又有叫法是称为模式对话框,无模式对话框等. 所谓模态对话框就是在 ...

  9. QT中的模态和非模态对话框

    模态对话框就是在我们没有关闭它之前,不能再与同一个应用程序的其他窗口进行交互,比如新建项目时弹出的对话框.要想使一个对话框成为模态对话框,只需要调用它的exec()函数: QDialog dialog ...

  10. windows对话框窗口DialogBox模式对话框、EndDialog、CreateDialog非模式对话框、DestroyWindow、WM_INITDIALOG

    普通窗口:自定义函数调用缺省函数 wndProc(-) { - DefWindowProc(-); } 对话框窗口:缺省函数 调用自定义函数 缺省函数(-){ - 自定义函数(-) - } 对话框原理 ...

最新文章

  1. 离散数学实验题目-图
  2. ubuntu导入第三方库_ubuntu用户切换、配置Python开发环境与所需的第三方库
  3. [nginx报错]---unknown directive chunkin in /XXXXX/XXXXXX:XX的几种解决方式
  4. layui根据name获取对象_layui表格行合并;解决侧边固定栏合并
  5. 长江浪花~朵儿朵尔朵
  6. CodeVs 1017 乘积最大(DP)
  7. 如何在Excel/Word中使用复选框
  8. 阿拉伯数字金钱转中文大写
  9. 区块链技术的应用价值了解下
  10. 用Delphi开发微信支付和支付宝支付生成签名并提交刷卡支付请求验证源码
  11. C#关于日期 月 天数 和一年有多少周及根据某年某周获取时间段的相关计算
  12. [一起来学mysql]-----MySQl的增删改查
  13. Docker、CentOS 8遭弃用,GPT-3、M1芯片撼动技术圈,盘点2020影响开发者的十大事件!...
  14. Python:照片墙设计,将爬虫获取的照片布局成爱心形状
  15. maven修改为阿里巴巴的仓库地址
  16. AcWing寒假每日一题 2058.笨拙的手指
  17. 2022张宇考研基础30讲 第十三讲 常微分方程
  18. Vue项目自定义滚动条样式【火狐、谷歌、360】
  19. 机器学习中precision和accuracy区别
  20. 业内人员告诉你银行测试到底做什么,怎么进银行测试.....

热门文章

  1. JavaScript分号使用指南
  2. 高德地图的测试key_获取高德地图key
  3. Keil 编译显示变量重复定义问题
  4. 平方米用计算机怎么计算公式,公式的换算和公式计算器
  5. 飞机大战(简单版)(C/C++) (VS)
  6. Alexa世界排名作弊分析
  7. Win10 LTSC 2019进入桌面时假死的拆中处理方法
  8. 怎么更新计算机显卡,显卡驱动怎么更新
  9. 常用单片机和开发板的引脚功能图
  10. 百度搜索排名优化和SEO搜索引擎优化