QT學習 之 對話方塊 (四) 字型對話方塊、訊息對話方塊、檔案對話方塊、程序對話方塊
QMessageBox類:
含有Question訊息框、Information訊息框、Warning訊息框和Critical訊息框等
通常有兩種方式可以來建立標準訊息對話方塊:
一種是採用“基於屬性”的API,一種是使用QMessageBox的靜態方法。
後者書寫容易,但缺少靈活性,針對使用者給出的提示的資訊不夠豐富,並且不能自定義訊息對話方塊裡面的按鈕提示資訊。因此推薦第一種寫法。
<span style="font-size:18px;">#include <QMessageBox> void MessageShow() { QMessageBox::StandardButton reply; // 列舉型變數 reply = QMessageBox::critical(this,tr("QMessageBox::cirtical()"), //有critical question information warning型別的訊息對話方塊 MESSAGE,QMessageBox::Abort | QMessageBox::Retry | QMessageBox::Ignore); // 此類按鈕還有如 OK HELP Yes No等等 if(reply == QMessageBox::Abort) { criticalLabel->setText(tr("Abort")); } else if(reply == QMessageBox::Retry) { criticalLabel->setText(tr("Retry")); } else { criticalLabel->setText(tr("Ignore")); } } </span>
這個例子是使用AMessageBox類的靜態方法,後面的例子中就是採用“基於屬性”的API方法。
QFileDialog類:
QFileDialog類提供了允許使用者選擇檔案或者目錄的對話方塊。
QFileDialog類允許使用者在它們的檔案系統上遍歷來選擇一個或多個檔案或目錄。
最簡單的方式是使用靜態函式來建立一個QFileDialog。在Windows上,這些靜態函式將呼叫本地Windows檔案對話方塊並且在Mac OS X上,這些靜態函式將呼叫本地Mac OS X檔案對話方塊。
<span style="font-size:18px;"> QString s = QFileDialog::getOpenFileName( "/home", "Images (*.png *.xpm *.jpg)", this, "open file dialog" "Choose a file" );</span>
在上面的例項中,一個模式對話方塊被使用靜態函式來建立。開始目錄被設定為“/home”。檔案過濾器被設定為“Images (*.png *.xpm *.jpg)”。檔案對話方塊的父物件被設定為this並且它被給定一個標識名稱——“open file dialog”。檔案對話方塊上面的標題被設定為“Choose a file”。
QFontDialog類:
標準字型對話方塊,一種是使用QFontDialog類的建構函式,一種是使用QFrontDialog類的靜態使用方法getFont()
例項:
<span style="font-size:18px;"> bool ok; QFont font = QFontDialog::getFont( &ok, QFont( "Helvetica [Cronyx]", 10 ), this ); if ( ok ) { // font被設定為使用者選擇的字型 } else { // 使用者取消這個對話方塊,font被設定為初始值,在這裡就是Helvetica [Cronyx], 10 }</span>
對話方塊也可以被用來直接設定視窗部件的字型:
myWidget.setFont( QFontDialog::getFont( 0, myWidget.font() ) );
如果使用者點選OK,它們選擇的字型將被myWidget使用,並且如果點選Cancel,最初的字型被使用。
QPageSetupDialog類:
不是很主流的類,配置與頁相關的印表機選項
QProgressDialog類:
QProgressDialog類提供了慢操作的進度的反饋。
進度對話方塊用於給使用者這個操作還要有多長時間的指示,並且證明這個應用程式還沒有凍結。它也給用於一箇中止這個操作執行的機會。
這裡有使用QProgressDialog的兩種方法:模式和非模式。
對於程式設計師,使用模式QProgressDialog是更簡單的,但是你必須呼叫qApp->processEvents()來保持事件迴圈的執行來確保應用程式沒有凍結。在迴圈中執行這個操作,在間隔中呼叫setProgress(),並且檢查wasCancelled()的取消。例如:
QProgressDialog progress( "Copying files...", "Abort Copy", numFiles,
this, "progress", TRUE );
for ( int i = 0; i < numFiles; i++ ) {
progress.setProgress( i );
qApp->processEvents();
if ( progress.wasCancelled() )
break;
//……複製檔案
}
progress.setProgress( numFiles );
你需要擁有一個正在執行的時間迴圈,把cancelled()訊號和停止這個操作的槽連線起來,並且在間隔中呼叫setProgress()。例如:
Operation::Operation( QObject *parent = 0 )
: QObject( parent ), steps( 0 )
{
pd = new QProgressDialog( "Operation in progress.", "Cancel", 100 );
connect( pd, SIGNAL(cancelled()), this, SLOT(cancel()) );
t = new QTimer( this );
connect( t, SIGNAL(timeout()), this, SLOT(perform()) );
t->start( 0 );
}
void Operation::perform()
{
pd->setProgress( steps );
//……執行操作的一個半分比
steps++;
if ( steps > pd->totalSteps() )
t->stop();
}
void Operation::cancel()
{
t->stop();
//……清除
你可以通過使用setLabel()、setBar()和setCancelButton()用自定製的視窗部件來替換子視窗部件來定製這兩種進度對話方塊。
下面是例子的原始碼
qbuiltingdlg.h
#ifndef QBUILTINDLG_H
#define QBUILTINDLG_H
#include <QMainWindow>
#include <QApplication>
#include <QPushButton>
#include <QDialog>
#include <QGridLayout>
#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <QTextEdit>
#include <QLineEdit>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QDialog>
#include <QtGui>
namespace Ui {
class QBuiltinDlg;
}
class QTextEdit;
class QPushButton;
class QBuiltinDlg : public QDialog
{
Q_OBJECT
public:
explicit QBuiltinDlg(QWidget* parent = 0);
virtual ~QBuiltinDlg();
private:
QTextEdit* displayTextEdit;
QPushButton* colorPushBtn;
QPushButton* errorPushBtn;
QPushButton* filePushBtn;
QPushButton* fontPushBtn;
QPushButton* inputPushBtn;
QPushButton* pagePushBtn;
QPushButton* progressPushBtn;
QPushButton* printPushBtn;
private slots:
void doPushBtn();
private:
Ui::QBuiltinDlg *ui;
};
#endif // QBUILTINDLG_H
qbuiltindlg.cpp
中間有很多註釋用於解釋,詳細的內容可以看文件
#include "qbuiltindlg.h"
#include "ui_qbuiltindlg.h"
QBuiltinDlg::QBuiltinDlg(QWidget *parent) :
QDialog(parent),
ui(new Ui::QBuiltinDlg)
{
displayTextEdit = new QTextEdit(tr("The standard text edit of QT"));
QGridLayout* gridLayout = new QGridLayout;
/*
*建立一個網格佈局管理器QGridLayout物件,gridLayout佈局管理器將會管理和排布所有的視窗部件。
*接下來,建立7個QPushButton物件,這些物件分別用來控制顏色對話方塊、錯誤訊息框、檔案對話方塊、字型對話方塊、輸入對話 框、頁設定對話方塊、進度對話方塊和列印對話方塊的建立和顯示。
*然後呼叫QGridLayout::addWidget()函式,將所有的QPushButton以及QTextEdit視窗部件排布在網格佈局管理器gridLayout中。
*最後,函式QDialog::setLayout()將網格佈局管理器gridLayout設定為內建對話方塊CBuiltinDlg物件的頂層佈局管理器。
*/
colorPushBtn = new QPushButton(tr("Color Dialog"));
errorPushBtn = new QPushButton(tr("Error Message"));
filePushBtn = new QPushButton(tr("File Dialog"));
fontPushBtn = new QPushButton(tr("Front Dialog"));
inputPushBtn = new QPushButton(tr("Input Dialog"));
pagePushBtn = new QPushButton(tr("PageSet Dialog"));
progressPushBtn = new QPushButton(tr("Process Dialog"));
printPushBtn = new QPushButton(tr("Printer Dialog"));
gridLayout->addWidget(colorPushBtn, 0, 0, 1, 1);
gridLayout->addWidget(errorPushBtn, 0, 1, 1, 1);
gridLayout->addWidget(filePushBtn, 0, 2, 1, 1);
gridLayout->addWidget(fontPushBtn, 1, 0, 1, 1);
gridLayout->addWidget(inputPushBtn, 1, 1, 1, 1);
gridLayout->addWidget(pagePushBtn, 1, 2, 1, 1);
gridLayout->addWidget(progressPushBtn, 2, 0, 1, 1);
gridLayout->addWidget(printPushBtn, 2, 1, 1, 1);
gridLayout->addWidget(displayTextEdit, 3, 0, 3, 3);
/*
*將所有的QPushButton物件的clicked()訊號關聯到內建對話方塊類CBuiltinDlg的槽函式doPushButton(),
*即所有QPushButton物件的 單擊操作都由統一的槽函式doPushButton()來處理。
*/
connect(colorPushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
connect(errorPushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
connect(filePushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
connect(fontPushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
connect(inputPushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
connect(pagePushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
connect(progressPushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
connect(printPushBtn, SIGNAL(clicked()), this, SLOT(doPushBtn()));
setWindowTitle(tr("Builtin"));
resize(400, 300);
setLayout(gridLayout);
}
QBuiltinDlg::~QBuiltinDlg()
{
delete ui;
}
void QBuiltinDlg::doPushBtn()
{
/*
*槽函式的開頭,首先是獲取傳送訊號的QPushButton物件的指標。函式QOjbect::sender()返回傳送訊號的物件的指標,返回型別 為QObject*。
*模板函式 T qobject_cast(QObject* object)
*完成型別的轉換,將<QOjbect*>型別的物件指標轉換為型別為<T *>的物件指標,如果轉換成功,返回正確的物件指標,否則 返回0。
*型別T必須是直接或間接繼承自QOjbect的類,並且在該類的定義裡有Q_OBJECT巨集變數(否則qobject_cast()函式的返回值是未定義的)。
*此外,可以認為一個類繼承自它自身。qobject_cast()模板函式的作用類似於標準C++的
*dynamic_cast()模板函式,不過qobject_cast()不需要執行時型別資訊(Run-Time Type Information, RTTI)的支援。
*/
QPushButton* btn = qobject_cast<QPushButton*>(sender());
/*
*if()條件判斷語句,判斷髮送訊號的物件是否是相應的QPushButton物件(colorBtn、errorPushBtn等),如果是則建立 相應的Qt內建對話方塊並進行顯示;
*否則將會跳過該段程式碼,直到找到條件為true的if()條件語句。
*/
if(btn == colorPushBtn)
{// 顏色對話方塊.
QPalette palette = displayTextEdit->palette();
const QColor& color = QColorDialog::getColor(palette.color(QPalette::Base), this);
if(color.isValid())
{
palette.setColor(QPalette::Base, color);
displayTextEdit->setPalette(palette);
}
}
/*
*上面這段程式碼是顏色對話方塊的例子,它的功能是利用Qt內建的顏色對話方塊QColorDialog類獲取使用者選擇的顏色,然後設定文字 編輯框的背景色。
*函式QTextEdit::palette()獲取文字編輯框物件displayTextEdit的調色盤。
*接下來,呼叫 QColorDialog::getColor()函式建立並顯示一個模態的顏色對話方塊,並返回使用者選擇的顏色物件的常量引用(對時物件的引用是無效的,必須使用常量引用)賦給變數color;
*如果使用者單擊“取消”按鈕,顏色對話方塊將返回一個無效的顏色;
*顏色對話方塊的顏色初始化為palette.color (QPalette::Base),即文字編輯框的背景色;父視窗部件為this。
*QColor::isValid() 函式判斷顏色對話方塊返回的顏色是否有效。如果顏色對話方塊返回的顏色是有效的,函式QPalette::setColor() 設 置調色盤的背景顏色為顏色對話方塊返回的顏色。
*此處的QPalette:: setColor() 函式具有2個引數,第1個引數QPalette::Base指定了調色盤的角色,
*告訴程式應該設定調色盤的所有三個顏色組中的哪一個角色的顏色(該函式將會影響到所有的三個顏色組);
*第2個引數 color 指定應該設定的顏色。最後,函式QtextEdit::setPalette()重新設定文字編輯框的調色盤。
*/
else if(btn == errorPushBtn)
{// 錯誤訊息框.
QErrorMessage box(this);
box.setWindowTitle(tr("Error Message"));
box.showMessage(tr("Error 1"));
box.showMessage(tr("Error 2"));
box.showMessage(tr("Error 3"));
box.showMessage(tr("Error 4"));
box.showMessage(tr("Error 5"));
box.exec();
}
/*
*該段程式碼是一個錯誤訊息框的例子。在這個例子中,多次呼叫了QErrorMessage::showMessage()函式,該函式的功能是在錯誤消 息框中顯示錯誤資訊。
*多次呼叫該函式,是為了演示顯示不同錯誤資訊、多個相同錯誤資訊以及錯誤訊息框的“再次顯示這個訊息”複選框選中與否的效果。
*最後,執行QErrorMessage::exec()顯示對話方塊。
*此為“基於屬性的”API方法
*/
else if(btn == filePushBtn)
{// 檔案對話方塊.
QString fileName = QFileDialog::getOpenFileName(this,tr("open the file"),"/home/czm",
tr("All files(*.*)"";;text files(*.txt)"";;XML files(*.xml)"));
displayTextEdit->setText(fileName);
}
/*
*該段程式碼開啟一個檔案對話方塊,獲取使用者選擇的檔名並顯示在文字編輯框中。此處,函式QFileDialog::getOpenFileName()具有4個引數。
*其中,實參 this 指定檔案對話方塊的父視窗部件;實參 tr("開啟檔案") 指定檔案對話方塊的標題;
*實參“/home/czm”指 定了檔案對話方塊的預設路徑;最後一個引數比較複雜,它指定了檔案對話方塊的多個檔案過濾器,過濾器之間通過兩個分 號“;;”間隔。
*如果使用者選擇了檔案,並單擊“確定”按鈕,那麼該檔案對話方塊將返回使用者選擇的檔名;而如果使用者單擊“取消”按 鈕,該對話方塊將返回一個NULL 字串。
*/
else if(btn == fontPushBtn)
{// 字型對話方塊.
bool ok;
const QFont& font = QFontDialog::getFont(&ok, displayTextEdit->font(),this,tr("字型對話方塊"));
if(ok)
{// 如果<確定>,設定字型.
displayTextEdit->setFont(font);
}
}
/*
*QFontDialog::getFont() 函式建立並顯示一個字型對話方塊。此處,該函式具有四個引數:
*第1個引數是一個輸出引數,用於標識用 戶的選擇狀態,如果使用者單擊“確定”按鈕,該字型對話方塊將會設定ok變數為true;而如果使用者單擊“取消”按鈕,ok將會被設定 為false。
*第2個引數指定了對話方塊的初始顏色,當用戶取消顏色的選擇時,字型對話方塊將初始顏色作為返回值。
*this引數指定了父視窗部件,最後一個引數指定了字型對話方塊的標題。
*/
else if(btn == inputPushBtn)
{// 輸入對話方塊.
bool ok;
QString text = QInputDialog::getText(this,tr("InputDialog"),tr("Please Input text"),
QLineEdit::Normal,QDir::home().dirName(),&ok);
if(ok && !text.isEmpty())
{
displayTextEdit->setText(text);
}
}
/*
*QInputDialog::getText()函式建立並顯示一個文字輸入對話方塊。
*前2個引數分別指定了輸入對話方塊的父視窗部件和對話方塊的標題;
*第3個引數指定了標籤的顯示文字;
*第4個引數指定了行編輯框QLineEdit輸入內容的顯示模式,此處 為QLineEdit::Normal,即按使用者輸入的實際內容顯示;
*第5個引數指定了行編輯框預設顯示的內容,函式QDir::home() 返回用 戶的home路徑,QDir::dirName()返回路徑的名字;
*最後一個引數和QFontDialog::getFont()函式的第1個引數的作用相同。
*/
else if(btn == pagePushBtn)
{// 頁設定對話方塊.
QPrinter printer;
QPageSetupDialog dlg(&printer, this);
dlg.setWindowTitle(tr("PageSet Dialog"));
if (dlg.exec() == QDialog::Accepted)
{
// 進行下一步的處理。
}
}
/*
*首先,定義了一個印表機QPrinter物件printer。
*然後建立了一個頁設定對話方塊QPageSetupDialog物件,並設定對話方塊的標題。
*在這個例子中,只是簡單地建立和顯示一個頁設定對話方塊,該對話方塊返回後沒有進行下一步的處理。
*/
else if(btn == progressPushBtn)
{// 進度對話方塊.
QProgressDialog progress(tr("Coping..."), tr("Cancel"),0,10000,this);
progress.setWindowModality(Qt::WindowModal);
progress.setWindowTitle(tr("Process Dialog"));
progress.show();
for(int i=0; i<10000; i++)
{
progress.setValue(i);
qApp->processEvents();
if(progress.wasCanceled())
break;
//... 複製檔案處理。
qDebug() << i;
}
progress.setValue(10000);
}
/*
*這一段程式碼建立了一個進度對話方塊,並模擬了顯示一個長時間操作的工作程序。
*首先,呼叫了QProgressDialog的建構函式,建立了一個進度對話方塊的棧物件。建構函式有5個引數。
*第1個引數是一個字串,它指定了顯示給使用者的提示資訊,表明當前正在進行的工作:
*第2個引數指定了“取消”按鈕的顯示文字,如果該引數為0的話,進度對話方塊將沒有“取消”按鈕,即建立進度對話方塊的程式碼為QProgressDialog progress(tr("Coping..."), 0 , 0, 10000, this)
*接下來的2個引數分別指定了操作的步數(在上面的例子中,可以假定進度對話方塊顯示覆制10 000個檔案的進展情況,
*第3個參 數設定為0,第4個引數設定為10 000,即這兩個引數的差值決定了這個複製操作的步數為10 000)。
*第5個引數指定了進度對話方塊的父視窗部件。
*接下來,函式setWindowModality()設定進度對話方塊的型別為Qt::WindowModal,即為模態對話方塊。
*有兩種方式使用進度對話方塊QProgressDialog:模態對話方塊方式。
*使用一個模態進度對話方塊顯示長時間操作的工作進度對於程式設計是比較簡單的,
*但是必須呼叫QApplication::processEvents()函式或者QEventLoop::processEvents(QEventLoop::ExcludeUserInputEvents)函式以保證事件迴圈還可以處理其他事件,
*以防止應用程式因為長時間的操作而導致沒有反應。
*在自定義對話方塊的例子中,使用了模態進度對話方塊,通過QProgressDialog::setValue()函式推進顯示的進度;
*通過QProgressDialog::wasCancled()函式判斷使用者是否中途選擇 了“取消”按鈕,如果是,將中斷複製檔案操作。
*此外,程式碼使用了qDebug()函式列印for()語句的執行進度,模擬複製操作。
*非模態對話方塊方式。非模態進度對話方塊適用於顯示在後臺執行的長時間操作的工作進度,這樣的話,使用者就能夠和應用程式 的其他視窗進行互動。
*/
else if(btn == printPushBtn)
{// 列印對話方塊.
QPrinter printer;
QPrintDialog dlg(&printer, this);
dlg.setWindowTitle(tr("Printer Dialog"));
if (dlg.exec() == QDialog::Accepted)
{
// 進行下一步的處理。
}
}
}
main.cpp
#include <QApplication>
#include "qbuiltindlg.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QBuiltinDlg w;
w.show();
return a.exec();
}
補充閱讀:
QPalette類包含了Qt視窗部件的顏色組(color group):
— Active組,該組的顏色用於當前活躍的(active)視窗,即具有鍵盤或滑鼠焦點的視窗;
— Inactive組,該組用於其他的視窗;
— Disabled組,該組用於狀態為不可用的(disabled)的子視窗部件(不包含視窗)。
所有Qt視窗部件都擁有一個調色盤並使用它繪製自己。通常,活躍狀態的視窗的標題欄顯示為藍色的,而非活躍(inactive)狀 態的視窗的標題欄顯示為灰色的;活躍狀態的視窗和非活躍狀態的視窗都可以包含狀態為不可用的視窗部件,一個不可用的窗 口部件(包括該視窗部件包含的子視窗部件)顯示為灰色的,使用者是無法與它進行互動的。通過改變視窗部件的調色盤的各個 組中的顏色,能夠改變視窗部件的顯示顏色,比如改變背景色、文字顏色等。
可以通過QWidget::palette()獲取一個視窗部件的調色盤,然後通過QWidget::setPalette()函式為該視窗部件設定修改後的調色盤。 或者通過QApplication::palette() 函式獲取應用程式的調色盤,並通過QApplication::setPalette() 為該應用程式設定修改後的調色 板。修改一個視窗部件的調色盤只會影響到該視窗部件以及子視窗部件(不包含子視窗);而改變一個應用程式的調色盤將會 影響到該應用程式的所有視窗部件。當對一個視窗部件的調色盤已經作了修改後,再對其父視窗部件調色盤的修改不會影響到該視窗部件的調色盤;同樣,對應用程式調色盤的修改不會影響已經單獨做出了調色盤修改的視窗部件。
調色盤類QPallete提供了顏色角色(color roles)概念,是指當前GUI介面中顏色的職責,通過列舉變數QPalette::ColorRole來定 義,比較常用的顏色角色有:
— QPalette::Window,通常指視窗部件的背景色;
— QPalette::WindowText,通常指視窗部件的前景色;
— QPalette::Base,指文字輸入視窗部件(比如QTextEdit、QLineEidt等)的背景色
— QPalette::Text,與QPalette::Base一塊使用,指文字輸入視窗部件的前景色;
— QPalette::Button,指按鈕視窗部件的背景色;
— QPalette::ButtonText,指按鈕視窗部件的前景色。