【Ctrl + F窗口】
finddialog.h:
#ifndef FINDDIALOG_H
#define FINDDIALOG_H
#include <QDialog>
class QCheckBox;
class QLabel;
class QLineEdit;
class QPushButton;
class FindDialog : public QDialog
{
Q_OBJECT
public:
FindDialog(QWidget *parent = 0);
signals:
void findNext(const QString &str, Qt::CaseSensitivity cs);
void findPrevious(const QString &str, Qt::CaseSensitivity cs);
private slots:
void findClicked();
void enableFindButton(const QString &text);
private:
QLabel *label;
QLineEdit *lineEdit;
QCheckBox *caseCheckBox;
QCheckBox *backwardCheckBox;
QPushButton *findButton;
QPushButton *closeButton;
};
#endif
第6行到第8行声明了一些用于这个对话框实现中的Qt类。前置声明会告诉C++编译程序类的存在,而不用提供类定义中的所有细节。
自定义类FindDialog 让他成为QDialog的子类:
对于所有定义了信号和槽的类,在类定义开始处的Q_OBJECT是必要的。
构造函数 parent指定了它的父窗口部件,如果为0证明它没有父窗口。
Qt::CaseSensitivity 是一个枚举,它有Qt::CaseSensitive 和 Qt::CaseInsensitive俩个取值。
signals 关键字本质是一个宏。
没有必要在头文件中就去访问(如<QCheckBox><QLabel>),
只是前置声明,可以提高编译过程的速度。
#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 &backward"));
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());
}
void FindDialog::findClicked()
{
QString text = lineEdit->text();
Qt::CaseSensitivity cs =
caseCheckBox->isChecked() ? Qt::CaseSensitive
: Qt::CaseInsensitive;
if (backwardCheckBox->isChecked()) {
emit findPrevious(text, cs);
} else {
emit findNext(text, cs);
}
}
void FindDialog::enableFindButton(const QString &text)
{
findButton->setEnabled(!text.isEmpty());
}
包含<QtGui>该头文件包含了Qt GUI类的定义。
类似的模块还有QtCore,QtGui,QtNetwork,QtOpenGL,QtScript,QtSql,QtXML
其中在<QtGui>中构成了QtCore和QtGui组成部分的所有类进行了定义。
包含这个头文件就能够省去我们在每个类中分别包含的麻烦。
意思就是说,就头文件中包含一个<QtGui>即可,不用每次都包含<QCheckBox>等。但是在头文件包含一个<QtGui>那么大的头文件是一种不好的编程风格。
在字符串周围的tr()函数调用是把它们翻译成其他语言的标记。在每个QObject对象以及包含有Q_OBJECT宏的子类中都有这个函数的声明。尽管我们不去使用翻译这个功能,但是这还是一个不错的习惯呢。
在字符串中使用了 "&"符号来表示快捷键。例如,第11行创建了一个Find按钮,用户可以在支持快捷键的平台下使用Alt+F快捷键激活它。
label->setBuddy(lineEdit):设置了行编辑器作为标签的伙伴。。。就是它可以再按下标签的快捷键时接受焦点。
setDefault(true)让Find按钮成为对话框的默认按钮。意义就是按下enter键时能够按下对应的按钮。
setEnabled(false)禁用了按钮,使按钮变为不可用状态。
由于QObject是FindDialog的父对象之一,所有可以省略connect()函数前面的QObject::前缀。
布局管理控件,那里的代码比较好理解,addStretch主要是为了能很好的占据它本来应该占有的区域。
sizeHint().height();可以返回一个窗口部件所理想的大小。
不需要再析构函数处delete来释放内存控件,因为Qt在删除父对象的时候自动删除其所属的所有子对象,也就会删除FindDialog中作为其子孙的所有子窗口部件和子布局。