接著前一篇,下面是源代碼部分:
#include <QtGui>
#include "finddialog.h"
FindDialog::FindDialog(QWidget *parent)
: QDialog(parent)
{
label = new QLabel(tr("Find &what:"));
lineEdit = new QLineEdit;
label->setBuddy(lineEdit);
caseCheckBox = new QCheckBox(tr("Match &case"));
backwardCheckBox = new QCheckBox(tr("Search &backford"));
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
findButton->setEnabled(false);
closeButton = new QPushButton(tr("Close"));
connect(lineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(enableFindButton(const QString&)));
connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
topLeftLayout->addWidget(lineEdit);
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addLayout(topLeftLayout);
leftLayout->addWidget(caseCheckBox);
leftLayout->addWidget(backwardCheckBox);
QVBoxLayout *rightLayout = new QVBoxLayout;
rightLayout->addWidget(findButton);
rightLayout->addWidget(closeButton);
rightLayout->addStretch();
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addLayout(leftLayout);
mainLayout->addLayout(rightLayout);
setLayout(mainLayout);
setWindowTitle(tr("Find"));
setFixedHeight(sizeHint().height());
}
FindDialog::~FindDialog()
{
}
void FindDialog::findClicked()
{
QString text = lineEdit->text();
Qt::CaseSensitivity cs = caseCheckBox->isChecked() ? Qt::CaseInsensitive : Qt::CaseSensitive;
if(backwardCheckBox->isChecked()) {
emit findPrevious(text, cs);
} else {
emit findNext(text, cs);
}
}
void FindDialog::enableFindButton(const QString &text)
{
findButton->setEnabled(!text.isEmpty());
}
CPP 文件要長(zhǎng)一些哦——不過(guò),它們的價(jià)錢(qián)也會(huì)更高,嘿嘿——嗯,來(lái)看代碼,第一行 include 的是QtGui。Qt 是分模塊的,記得我們建工程的時(shí)候就會(huì)問(wèn)你,使用哪些模塊?QtCore?QtGui?QtXml?等等。這里,我們引入 QtGui,它包括了 QtCore 和 QtGui 模塊。不過(guò),這并不是最好的做法,因?yàn)镼tGui 文件很大,包括了 GUI 的所有組件,但是很多組件我們根本是用不到的——就像 Swing 的import,你可以 import 到類(lèi),也可以使用,不過(guò)都不會(huì)建議使用,這里也是一樣的。我們最好只引入需要的組件。不過(guò),那樣會(huì)把文件變長(zhǎng),現(xiàn)在就先用 QtGui 啦,只要記得正式開(kāi)發(fā)時(shí)不能這么用就好啦!
構(gòu)造函數(shù)有參數(shù)初始化列表,用來(lái)調(diào)用父類(lèi)的構(gòu)造函數(shù),相當(dāng)于 Java 里面的 super()函數(shù)。這是 C++ 的相關(guān)知識(shí),不是 Qt 發(fā)明的,這里不再贅述。
然后新建一個(gè) QLabel。還記得前面的 Hello, world!里面也使用過(guò) QLabel 嗎?那時(shí)候只是簡(jiǎn)單的傳入一個(gè)字符串??!這里怎么是一個(gè)函數(shù) tr()?函數(shù) tr()全名是 QObject::tr(),被它處理的字符串可以使用工具提取出來(lái)翻譯成其他語(yǔ)言,也就是做國(guó)際化使用。這以后還會(huì)仔細(xì)講解,只要記住,Qt 的最佳實(shí)踐:如果你想讓你的程序國(guó)際化的話(huà),那么,所有用戶(hù)可見(jiàn)的字符串都要使用 QObject::tr()!但是,為什么我們沒(méi)有寫(xiě) QObject::tr(),而僅僅是 tr()呢?原來(lái),tr()函數(shù)是定義在 Object里面的,所有使用了 Q_OBJECT 宏的類(lèi)都自動(dòng)具有 tr()函數(shù)。
字符串中的&代表快捷鍵。注意看下面的 findButton 的 &Find,它會(huì)生成 Find 字符串,當(dāng)你按下Alt+F 的時(shí)候,這個(gè)按鈕就相當(dāng)于被點(diǎn)擊——這么說(shuō)很難受,相信大家都明白什么意思。同樣,前面label 里面也有一個(gè)&,因此它的快捷鍵就是 Alt+W。不過(guò),這個(gè) label 使用了 setBuddy 函數(shù),它的意思是,當(dāng) label 獲得焦點(diǎn)時(shí),比如按下 Alt+W,它的焦點(diǎn)會(huì)自動(dòng)傳給它的 buddy,也就是lineEdit??矗@就是伙伴的含義(buddy 英文就是伙伴的意思)。
后面幾行就比較簡(jiǎn)單了:創(chuàng)建了兩個(gè) QCheckBox,把默認(rèn)的按鈕設(shè)為 findButton,把 findButton 設(shè)為不可用——也就是變成灰色的了。
再下面是三個(gè) connect 語(yǔ)句,用來(lái)連接信號(hào)槽??梢钥吹?,當(dāng) lineEdit 發(fā)出 textChanged(const QString&)信號(hào)時(shí),F(xiàn)indDialog 的 enableFindButton(const QString&)函數(shù)會(huì)被調(diào)用——這就是回調(diào),是有系統(tǒng)自動(dòng)調(diào)用,而不是你去調(diào)用——當(dāng) findButton 發(fā)出 clicked()信號(hào)時(shí),F(xiàn)indDialog的 findClicked()函數(shù)會(huì)被調(diào)用;當(dāng) closeButton 發(fā)出 clicked()信號(hào)時(shí),F(xiàn)indDialog 的 close()函數(shù)會(huì)被調(diào)用。注意,connect()函數(shù)也是 QObject的,因?yàn)槲覀兝^承了 QObject,所以能夠直接使用。
后面的很多行語(yǔ)句都是 layout 的使用,雖然很復(fù)雜,但是很清晰——編寫(xiě) layout 布局最重要一點(diǎn)就是思路清楚,想清楚哪個(gè)套哪個(gè),就會(huì)很好編寫(xiě)。這里我們的對(duì)話(huà)框?qū)嶋H上是這個(gè)樣子的:
注意那個(gè) spacer 是由 rightLayout 的 addStretch()添加的,就像彈簧一樣,把上面的組件“頂起來(lái)”。
最后的 setWindowTitle()就是設(shè)置對(duì)話(huà)框的標(biāo)題,而 setFixedHeight()是設(shè)置成固定的高度,其參數(shù)值 sizeHint()返回“最理想”的大小,這里我們使用的是 height()函數(shù)去到“最理想”的高度。
好了,下面該編寫(xiě)槽了——雖然說(shuō)是 slot,但實(shí)際上它就是普通的函數(shù),既可以和其他函數(shù)一樣使用,又可以被系統(tǒng)回調(diào)。
先看 findClicked()函數(shù)。首先取出 lineEdit的輸入值;然后判斷 caseCheckBox是不是選中,如果選中就返回 Qt::CaseInsensitive,否則返回 Qt::CaseSensitive,用于判斷是不是大小寫(xiě)敏感的查找;最后,如果 backwardCheckBox被選中,就 emit(發(fā)出)信號(hào) findPrevious(),否則 emit信號(hào) findNext。
enableFindButton()則根據(jù) lineEdit 的內(nèi)容是不是變化——這是我們的 connect 連接的——來(lái)設(shè)置findButton 是不是可以使用,這個(gè)很簡(jiǎn)單,不再說(shuō)了。
這樣,F(xiàn)indDialog.cpp 也就完成了。下面編寫(xiě) main.cpp——其實(shí) QtCreator 已經(jīng)替我們完成了——
#include <QApplication>
#include "finddialog.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
FindDialog *dialog = new FindDialog;
dialog->show();
return app.exec();
}
運(yùn)行一下看看我們的成果吧!
雖然很簡(jiǎn)單,也沒(méi)有什么實(shí)質(zhì)性的功能,但是我們已經(jīng)能夠制作對(duì)話(huà)框了—— Qt 的組件成百上千,不可能全部介紹完,只能用到什么學(xué)什么,更重要的是,我們已經(jīng)了解了其編寫(xiě)思路,否則的話(huà),即便是你拿著全世界所有的磚瓦,沒(méi)有設(shè)計(jì)圖紙,你也不知道怎么把它們組合成高樓大廈??!
嘿嘿,下回見(jiàn)!
本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/194031
更多建議: