天天看點

Qt中的對話框

  對話框是GUI程式和使用者進行簡短互動的頂層視窗,所謂頂層視窗即始終在主視窗之上顯示。QDialog是Qt所有類型的對話框視窗的基類,它繼承于QWidget,是一種容器類型元件。

Qt中的對話框

  QWidget是所有視窗類的抽象,它也可以生成對話框,但是對話框是常見的視窗元件,若每次要使用對話框,都利用QWidget來生成并設定相關參數,顯然十分繁瑣。是以Qt為我們封裝了另外一個子類QDialog,專門用于生成對話框。

1. 模态和非模态對話框

  對話框歸為兩大類,即模态對話框于非模态對話框。

  模态對話框(QDialog::exec())

  阻塞型的對話框,顯示後無法與父視窗進行互動。如word文檔中修改源檔案内容後直接關閉視窗彈出的對話框:

Qt中的對話框

  非模态對話框(QDialog::show())

  非阻塞型的對話框,顯示後還可以與父視窗進行互動。如word文檔的替換操作:

Qt中的對話框

  模态對話框:

  (1) 定義一個主視窗,視窗内有一個按鈕:

//Widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui/QApplication>
#include <QWidget>
#include <QPushButton>
#include <QDebug>

class Widget : public QWidget
{
    Q_OBJECT            //表要類要使用信号與槽機制
protected:
    QPushButton Btn;    //按鈕
protected slots:
    void Btn_Clicked(); //槽,用于響應按鈕按下操作
public:
    Widget(QWidget *parent = ); //parent預設參數為0,表預設是容器類父視窗
    ~Widget();
};

#endif // WIDGET_H

//Widget.cpp
#include "Widget.h"
#include "Dialog.h"

//Widget的構造函數,Btn初始化為其Widget的功能類字子元件
Widget::Widget(QWidget *parent) : QWidget(parent), Btn(this)
{
    Btn.resize(, );
    Btn.move(, );
    Btn.setText("btn");

    resize(, );
    setWindowTitle("hello");
    connect(&Btn, SIGNAL(clicked()), this, SLOT(Btn_Clicked()));
}

Widget::~Widget()
{
}

//Widget内按鈕的響應槽,該按鈕按下後Winget會彈出對話框(Dialog)
void Widget::Btn_Clicked()
{
    qDebug() << "Btn_Clicked()";
    Dialog d(this);     //Dialog是對話框類,見下
    int ret = d.exec(); //exec()表明d是個模态對話框,使用者不操作該對話框,會阻塞于此。
                        //exec()傳回對話框的運作結果
    if (ret == Dialog::Accepted)
    {
        qDebug() << "Accepted";
    }
    else if (ret == Dialog::Rejected)
    {
        qDebug() << "Rejected";
    }
}
           

  (2) 定義一個對話框,框内有兩個按鈕

//Dialog.h
#ifndef DIALOG_H
#define DIALOG_H

#include <QWidget>
#include <QDebug>
#include <QPushButton>
#include <QtGui/QDialog>

class Dialog : public QDialog
{
    Q_OBJECT
protected:
    QPushButton Btn1;   //對話框内按鈕1
    QPushButton Btn2;   //對話框内按鈕2
protected slots:
    void Btn1_Clicked();    //按鈕1的槽
    void Btn2_Clicked();    //按鈕2的槽
public:
    Dialog(QWidget *parent = );
    ~Dialog();
};

#endif // DIALOG_H

#include "Dialog.h"

//Dialog類的構造函數,初始化清單指定兩個按鈕的父視窗都為Dialog
Dialog::Dialog(QWidget *parent) : QDialog(parent), Btn1(this), Btn2(this)
{
    //初始化按鈕1
    Btn1.setText("Btn1");
    Btn1.move(, );
    Btn1.resize(, );

    //初始化按鈕2
    Btn2.setText("Btn2");
    Btn2.move(, );
    Btn2.resize(, );

    //初始化對話框的大小以及設定其名字
    this->resize(, );
    this->setWindowTitle("Dialog");

    //信号與槽的映射
    connect(&Btn1, SIGNAL(clicked()), this, SLOT(Btn1_Clicked()));
    connect(&Btn2, SIGNAL(clicked()), this, SLOT(Btn2_Clicked()));
}

Dialog::~Dialog()
{    
}

//按鈕1的槽
void Dialog::Btn1_Clicked()
{
    qDebug() << "Btn1_Clicked()";
    done(Accepted);
}

//按鈕2的槽
void Dialog::Btn2_Clicked()
{
    qDebug() << "Btn2_Clicked()";
    done(Rejected);
}
           

  (3) main函數

//main.cpp
#include "Dialog.h"
#include "Widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;

    w.show();

    return a.exec();
}
           

  隻有模态對話框才有傳回值的概念,傳回值用于表示對話框和使用者的互動結果。函數:

void QDialog::done(int);
           

  用于關閉對話框并将參數i作為與使用者的互動結果,發回給exec()的調用處。i的取值可為Accepted、Rejected或其其他int型資料,Accepted、Rejected是在QDialog類中定義的枚舉類型,前者表示使用者操作成功,後者表示操作失敗。

  非模态對話框:

  在棧中建立模态對話框是常用的方式,而非模态對話框由于其顯示函數是非阻塞的,是以需要在堆中建立。Widget::Btn_Clicked()函數改寫為:

void Widget::Btn_Clicked()
{
    qDebug() << "Btn_Clicked()";

    Dialog* d = new Dialog();
    d->setAttribute(Qt::WA_DeleteOnClose);
    d->show();

    qDebug() << "Btn_Clicked() exit!";
}
           

  show()函數是非阻塞的,對話框Dialog對象d若是在棧中生成那函數退出後對話框也随之消失,是以非模态對話框需在堆中動态生成,這樣該函數退出後對話框仍能顯示,但是卻也出現了新的問題:指針d執行動态生成的空間,一旦該函數退出後,d指針将失效,這也就意味着其他函數無法釋放該堆空間,造成記憶體洩漏。是以Qt提供了“對話框被使用者關閉後就釋放給對話框占據的堆空間”的操作:

  Qt對話框的模态/非模态是通過對話框的屬性變量modal确定的,modal是個bool類型的變量,預設情況下是false,即非模态,是以調用show()函數顯示對話框時是非模态的;調用exec()函數顯示時,它将忽略modal的屬性值的設定并将對話框設定為模态對話框。

  除了模态、非模态,還有一種混合特性的對話框,即通過QDialog::setModal()函數設定modal變量為true,那麼該對話框将變成:對話框在堆中配置設定,同時用show()顯示的前提下,同時又是模态對話框。

QDialog* dialog = new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModal(true);
dialog->show();
           

2. Qt中定義的常用對話框

  Qt提供了一些可複用的常用對話框類,這些類都繼承自QDialog類,有描述提示型消息的QMessageBox、描述檔案相關的QFileDialog、描述列印機選擇的QPrintDialog,描述顔色選擇的QColorDialog等等。

  對于這些對話框類的使用,都遵循如下規則:

//1. 定義對話框
Dialogxxx d(this);

//2. 設定對話框屬性,如對話框标題、文字顯示
d.setxxx(xxx);

//3. 判斷對話框被使用者操作後的傳回值,
if (d.exec() == Dialogxxx::xxx)
{
    //執行相關操作
}
           

  下面是上述Qt實作好的對話框類的使用,它們定義在Widget類型的父類視窗類中的按鈕槽函數中。

2.1 消息對話框

  消息對話框主要用于為使用者提示消息,強制使用者進行選擇:

//提示使用者消息
#include <QMessageBox>

//強制使用者選擇
QMessageBox msg(this);              //建立對話框
msg.setWindowTitle("xxxx");         //設定對話框标題
msg.setText("customMsgBtnClicked"); //設定對話框的提示資訊
msg.setIcon(QMessageBox::Warning);  //設定對話框的圖示
//設定對話框的按鈕
msg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel | QMessageBox::YesToAll);  

QMessageBox msg(this);
msg.setText("this is a message dialog!");
msg.exec();
           

  運作結果:

Qt中的對話框

2.2 檔案對話框

  在GUI程式中,打開檔案和儲存檔案的時候都會彈出對話框,

//GUI程式要打開系統上的檔案
#include <QFileDialog>

QFileDialog d(this);                        //建立對話框
d.setAcceptMode(QFileDialog::AcceptOpen);   //設定該對話框的模式為打開
d.setFileMode(QFileDialog::ExistingFiles);  //選擇打開的是檔案,ExistingFiles表可選擇多檔案,
                                            //ExistingFile則表示隻能選擇一個檔案,目錄則是QFileDialog::Directory
d.setFilter("TEXT(*.txt)");                 //以檔案格式過濾掉檔案

if (d.exec() == QFileDialog::Accepted)      //執行成功
{
    QStringList fs = d.selectedFiles();     //列印使用者選擇的結果

    for (int i = ; i < fs.count(); i++)
    {
        qDebug() << fs[i];
    }
}
           

  運作結果:

Qt中的對話框
//GUI程式要儲存檔案
QFileDialog d(this);
d.setAcceptMode(QFileDialog::AcceptSave);
//d.setFilter("c(*.c)");

if (d.exec() == QFileDialog::Accepted)
{
    QStringList fs = d.selectedFiles();

    for (int i = ; i < fs.count(); i++)
    {
        qDebug() << fs[i];
    }
}
           

  運作:

Qt中的對話框

2.3 顔色對話框

#include <QColorDialog>
QColorDialog d(this);
d.setWindowTitle("color editor");

if (d.exec() == QColorDialog::Accepted)
{
    QColor color = d.selectedColor();
    qDebug() << color;
    qDebug() << color.red();
    qDebug() << color.green();
    qDebug() << color.blue();
}
           

  運作:

Qt中的對話框

  setCurrentColor()函數用于設定目前的顔色值:

  QColor類用于表現顔色值,該類有一個構造函數:

QColor ( int r, int g, int b, int a =  )
           

2.4 輸入對話框

  輸入對話框QInputDialog類,用于需要臨時進行資料輸入的場合:

QInputDialog d(this);
d.setWindowTitle("input dat");
d.setLabelText("ple input dat");
d.setInputMode(QInputDialog::IntInput);  //TextInput輸入文本,DoubleInput輸入double類型
if (d.exec() == QInputDialog::Accepted)
    qDebug() << d.intValue();           //TextValue、doubleValue
           

  運作:

Qt中的對話框

2.5 字型對話框

  QFontDialog類用于選擇字型的對話框:

#include <QFontDialog>
QFontDialog f(this);
f.setWindowTitle("font select");
f.setCurrentFont(QFont(QFont("gargi", , QFont::Bold)));   //設定彈出的對話框的選擇的字型

if (f.exec() == QFontDialog::Accepted)
{
    qDebug() << f.selectedFont();
}
           

運作:

Qt中的對話框

2.6 進度對話框

  QProgressDialog類用于顯示進度資訊,不需要判斷exec()函數的傳回值:

#include <QProgressDialog>
QProgressDialog d(this);
d.setWindowTitle("load");

//設定範圍值
d.setMinimum();
d.setMaximum();

//設定進度數值
d.setValue();

//設定提示資訊
d.setLabelText("xxxxxxxx");

d.exec();
           

運作:

Qt中的對話框

2.7 列印對話框

  QPrinter類封裝了列印裝置驅動及其參數,利用該類尅以相同的方式使用系統的不同的列印裝置列印。

#include <QPrintDialog>
#include <QTextDocument>
#include <QPrinter>

QPrintDialog d(this);
d.setWindowTitle("print test");

if (d.exec() == QPrintDialog::Accepted)
{
    QPrinter *p = d.printer();
    QTextDocument td;

    //可以通過列印機列印,這裡是列印到文本檔案
    td.setPlainText("print test!!");    //待列印的文本
    p->setOutputFileName("./tt.txt");   //列印到此檔案
    td.print(p);
}
           

運作:

Qt中的對話框