Linux下QT实现自定义对话框以及设置模态和非模态对话框
2013-07-24 20:44
447 查看
最近使用QT做毕业设计,其中用到了对话框,但系统默认的对话框不能满足我的需求,于是决定自己来封装一个,这需要根据QT提供的QDialog基类来建立,以下附上头文件及实现文件,已测试通过。
对话框分为模态对话框和非模态对话框。所谓模态对话框,就是会阻塞同一应用程序中其它窗口的输入。模态对话框很常见,比如“打开文件”功能。你可以尝试一下记事本的打开文件,当打开文件对话框出现时,我们是不能对除此对话框之外的窗口部分进行操作的。与此相反的是非模态对话框,例如查找对话框,我们可以在显示着查找对话框的同时,继续对记事本的内容进行编辑。
Qt
支持模态对话框和非模态对话框。其中,Qt 有两种级别的模态对话框:应用程序级别的模态和窗口级别的模态,默认是应用程序级别的模态。应用程序级别的模态是指,当该种模态的对话框出现时,用户必须首先对对话框进行交互,直到关闭对话框,然后才能访问程序中其他的窗口。窗口级别的模态是指,该模态仅仅阻塞与对话框关联的窗口,但是依然允许用户与程序中其它窗口交互。窗口级别的模态尤其适用于多窗口模式,更详细的讨论可以看以前发表过的文章。
Qt
使用 QDialog::exec() 实现应用程序级别的模态对话框,使用 QDialog::open() 实现窗口级别的模态对话框,使用 QDialog::show() 实现非模态对话框。模态对话框即当对话框出现时,我们不能与主窗口进行任何交互,直到我们关闭了该对话框。
函数不会阻塞当前线程,对话框会显示出来,然后函数立即返回,代码继续执行。注意,dialog 是建立在栈上的,show() 函数返回,MainWindow::open() 函数结束,dialog 超出作用域被析构,因此对话框消失了。知道了原因就好改了,我们将 dialog 改成堆上建立,当然就没有这个问题了:
如果你足够细心,应该发现上面的代码是有问题的:dialog
存在内存泄露!dialog 使用 new 在堆上分配空间,却一直没有 delete。解决方案也很简单:将 MainWindow 的指针赋给 dialog 即可。不过,这样做有一个问题:如果我们的对话框不是在一个界面类中出现呢?由于 QWidget 的 parent 必须是 QWidget 指针,那就限制了我们不能将一个普通的 C++ 类指针传给 Qt 对话框。另外,如果对内存占用有严格限制的话,当我们将主窗口作parent 时,主窗口不关闭,对话框就不会被销毁,所以会一直占用内存。在这种情景下,我们可以设置
dialog 的 WindowAttribute:
函数设置对话框关闭时,自动销毁对话框。另外,QObject 还有一个 deleteLater() 函数,该函数会在当前事件循环结束时销毁该对话框(具体到这里,需要使用 exec() 开始一个新的事件循环)。
#ifndef MYRMDIALOG_H #define MYRMDIALOG_H #include <QDialog> #include <QCheckBox> #include <QDateTimeEdit> #include <QDateEdit> #include <QTimeEdit> #include <QPushButton> #include <QHBoxLayout> #include <QVBoxLayout> class MyRmDialog : public QDialog { Q_OBJECT public: MyRmDialog(QWidget *parent = 0); private: QDateTimeEdit *dateTimeEdit; QDateEdit *dateEdit; QTimeEdit *timeEdit; QCheckBox *everyDay; QPushButton *dateBtn; QPushButton *timeBtn; QPushButton *okBtn; QPushButton *cancelBtn; QHBoxLayout *editLayout; QHBoxLayout *spinLayout; QHBoxLayout *btnLayout; QVBoxLayout *mainLayout; private slots: void dateClicked(); void timeClicked(); void okClicked(); void cancelClicked(); void timeoutslot(); }; #endif // MYRMDIALOG_H.cpp
#include "MyRmDialog.h" #include <QTextCodec> #include <QTimer> MyRmDialog::MyRmDialog(QWidget *parent) : QDialog(parent) { QTextCodec::setCodecForTr(QTextCodec::codecForName("gbk")); setWindowTitle(tr("编辑提醒")); dateTimeEdit=new QDateTimeEdit; dateTimeEdit->setDate(QDate::currentDate()); dateTimeEdit->setTime(QTime::currentTime()); dateEdit=new QDateEdit(QDate::currentDate()); timeEdit=new QTimeEdit(QTime::currentTime()); dateEdit->setReadOnly(true); timeEdit->setReadOnly(true); dateBtn = new QPushButton(tr("设置日期")); connect(dateBtn,SIGNAL(clicked()),this,SLOT(dateClicked())); timeBtn = new QPushButton(tr("设置时间")); connect(timeBtn,SIGNAL(clicked()),this,SLOT(timeClicked())); everyDay=new QCheckBox; everyDay->setText(tr("每天提醒")); everyDay->setChecked(true); //默认为每天提醒 okBtn=new QPushButton(tr("确定")); connect(okBtn,SIGNAL(clicked()),this,SLOT(okClicked())); cancelBtn=new QPushButton(tr("取消")); connect(cancelBtn,SIGNAL(clicked()),this,SLOT(cancelClicked())); editLayout = new QHBoxLayout; spinLayout = new QHBoxLayout; btnLayout=new QHBoxLayout; mainLayout=new QVBoxLayout; editLayout->setSpacing(60); editLayout->addWidget(dateBtn); editLayout->addWidget(timeBtn); spinLayout->setSpacing(60); spinLayout->addWidget(dateEdit); spinLayout->addWidget(timeEdit); btnLayout->setSpacing(60); btnLayout->addWidget(okBtn); btnLayout->addWidget(cancelBtn);
mainLayout->setMargin(40); mainLayout->addWidget(dateTimeEdit); mainLayout->addLayout(editLayout); mainLayout->addLayout(spinLayout); mainLayout->addWidget(everyDay); mainLayout->addLayout(btnLayout); QTimer *timer=new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(timeoutslot())); setLayout(mainLayout); timer->start(1000); } void MyRmDialog::okClicked() { dateEdit->setReadOnly(true); timeEdit->setReadOnly(true); } void MyRmDialog::cancelClicked() { //这里实现自己的事件 } void MyRmDialog::dateClicked() { dateEdit->setReadOnly(false); connect(dateEdit,SIGNAL(dateChanged(QDate)),dateTimeEdit,SLOT(setDate(QDate))); } void MyRmDialog::timeClicked() { timeEdit->setReadOnly(false); connect(timeEdit,SIGNAL(timeChanged(QTime)),dateTimeEdit,SLOT(setTime(QTime))); } void MyRmDialog::timeoutslot() { QDate date=dateTimeEdit->date(); QTime time=dateTimeEdit->time(); QTime time1(23,59,59); if(time == time1) date = date.addDays(1); time = time.addSecs(1); dateTimeEdit->setDate(date); dateTimeEdit->setTime(time); }
对话框分为模态对话框和非模态对话框。所谓模态对话框,就是会阻塞同一应用程序中其它窗口的输入。模态对话框很常见,比如“打开文件”功能。你可以尝试一下记事本的打开文件,当打开文件对话框出现时,我们是不能对除此对话框之外的窗口部分进行操作的。与此相反的是非模态对话框,例如查找对话框,我们可以在显示着查找对话框的同时,继续对记事本的内容进行编辑。
Qt
支持模态对话框和非模态对话框。其中,Qt 有两种级别的模态对话框:应用程序级别的模态和窗口级别的模态,默认是应用程序级别的模态。应用程序级别的模态是指,当该种模态的对话框出现时,用户必须首先对对话框进行交互,直到关闭对话框,然后才能访问程序中其他的窗口。窗口级别的模态是指,该模态仅仅阻塞与对话框关联的窗口,但是依然允许用户与程序中其它窗口交互。窗口级别的模态尤其适用于多窗口模式,更详细的讨论可以看以前发表过的文章。
Qt
使用 QDialog::exec() 实现应用程序级别的模态对话框,使用 QDialog::open() 实现窗口级别的模态对话框,使用 QDialog::show() 实现非模态对话框。模态对话框即当对话框出现时,我们不能与主窗口进行任何交互,直到我们关闭了该对话框。
void MainWindow::open() { MyRmDialog dialog(this); dialog.setWindowTitle(tr("Hello, dialog!")); dialog->setModal(true); dialog.show(); }是不是事与愿违?对话框竟然一闪而过!这是因为,show()
函数不会阻塞当前线程,对话框会显示出来,然后函数立即返回,代码继续执行。注意,dialog 是建立在栈上的,show() 函数返回,MainWindow::open() 函数结束,dialog 超出作用域被析构,因此对话框消失了。知道了原因就好改了,我们将 dialog 改成堆上建立,当然就没有这个问题了:
void MainWindow::open() { QDialog *dialog = new QDialog; dialog->setWindowTitle(tr("Hello, dialog!")); dialog->setModal(true); dialog->show(); }最后两句也可直接用一句dialog->exec();
如果你足够细心,应该发现上面的代码是有问题的:dialog
存在内存泄露!dialog 使用 new 在堆上分配空间,却一直没有 delete。解决方案也很简单:将 MainWindow 的指针赋给 dialog 即可。不过,这样做有一个问题:如果我们的对话框不是在一个界面类中出现呢?由于 QWidget 的 parent 必须是 QWidget 指针,那就限制了我们不能将一个普通的 C++ 类指针传给 Qt 对话框。另外,如果对内存占用有严格限制的话,当我们将主窗口作parent 时,主窗口不关闭,对话框就不会被销毁,所以会一直占用内存。在这种情景下,我们可以设置
dialog 的 WindowAttribute:
void MainWindow::open() { QDialog *dialog = new QDialog; dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setWindowTitle(tr("Hello, dialog!")); dialog->show(); }setAttribute()
函数设置对话框关闭时,自动销毁对话框。另外,QObject 还有一个 deleteLater() 函数,该函数会在当前事件循环结束时销毁该对话框(具体到这里,需要使用 exec() 开始一个新的事件循环)。
相关文章推荐
- qt模态对话框 以及exec()事件循环简单实现
- 如何实现设置页面顶部添加导航栏,以及自定义风格
- 图形的绘制,如何使用自定义画笔(颜色,线宽,线形)。如何为程序中添加选项菜单和选项设置对话框,如何使用标准颜色对话框,如何使用字体对话框,在选项对话框中实现预览功能。实现选项对话框和窗口类中的数据交换。如何改变对话框和控件的背景色,如何改变控件的文本颜色,
- <Linux+Qt>QDialog的模态与非模态的对话框
- QT模态对话框和非模态对话框
- QT 自定义模态对话框
- qt button以及label实现不规则图形(五种方法:使用QSS,设置Mask图片,自己画)
- [IOS] 自定义AlertView实现模态对话框
- 自定义 AlertView 实现模态对话框
- QT模态对话框及非模态对话框学习
- Qt的模态对话框和非模态对话框
- 自定义 AlertView 实现模态对话框
- Android自定义对话框实现以及style的应用
- Qt对话框的生命周期及模态设置
- QT 模态对话框和非模态对话框
- Qt 中关于 模态对话框 和 非模态对话框的 3 种不同形式的 8 种情况(学习经验心得整理)
- 自定义 AlertView 实现模态对话框
- Qt模态对话框和非模态对话框
- MFC模态对话框和非模态对话框及副窗口调用主窗口控件 自定义消息发送
- 自己实现的数据表格控件(dataTable),支持自定义样式和标题数据、ajax等各种自定义设置以及分页自定义