#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() 開始一個新的事件循環)。