一、
新建一个工程,选择QT Application,工程名qtFindDlg;注意,BaseDialog选择QDialog,而不是默认的QMainWindow;点击“完成”。
程序完成运行效果如图:
上代码finddlg.h:
#ifndef FINDDLG_H #define FINDDLG_H #include <QtGui/QDialog> #include "ui_finddlg.h" class QCheckBox; class QLabel; class QLineEdit; class QPushButton; class FindDlg : public QDialog { Q_OBJECT public: FindDlg(QWidget *parent = 0, Qt::WFlags flags = 0); ~FindDlg(); 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: Ui::FindDlgClass ui; QLabel* m_pQLabel; QLineEdit* m_pQLineEdit; QCheckBox* m_pQCaseCheckBox; QCheckBox* m_pQBackwardCheckBox; QPushButton* m_pQFindButton; QPushButton* m_pQCloseButton; }; #endif // FINDDLG_H
对于所有定义了信号和槽的类,在类定义开始处的Q_OBJECT宏都是必需的。
Signals部分声明了当用户单击Find按钮时对话框所发射的信号。
Signals关键字实际上是一个宏。C++预处理器会在编译程序找到它之前把它转换成标准C++代码。
之后private slots:声明了两个槽。为了实现这两个槽,几乎需要访问这个对话框的所有子窗口部件(控件),所以也就保留了指向这些子窗口部件的指针。关键字slots如同signals一样也是一个宏。
下面是finddlg.cpp的代码
#include <QtGui> #include "finddlg.h" #include <iostream> #include <exception> FindDlg::FindDlg(QWidget *parent, Qt::WFlags flags) : QDialog(parent, flags) { ui.setupUi(this); try { m_pQLabel = new QLabel(tr("Find &what:")); m_pQLineEdit = new QLineEdit; m_pQLabel->setBuddy(m_pQLineEdit); m_pQCaseCheckBox = new QCheckBox(tr("Match &case")); m_pQBackwardCheckBox = new QCheckBox(tr("Search &backford")); m_pQFindButton = new QPushButton(tr("&Find")); m_pQFindButton->setDefault(true); m_pQFindButton->setEnabled(false); m_pQCloseButton = new QPushButton(tr("Cl&ose")); connect(m_pQLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(enableFindButton(const QString&))); connect(m_pQFindButton, SIGNAL(clicked()), this, SLOT(findClicked())); connect(m_pQCloseButton, SIGNAL(clicked()), this, SLOT(close())); QHBoxLayout *topLeftLayout = new QHBoxLayout; topLeftLayout->addWidget(m_pQLabel); topLeftLayout->addWidget(m_pQLineEdit); QVBoxLayout *leftLayout = new QVBoxLayout; leftLayout->addLayout(topLeftLayout); leftLayout->addWidget(m_pQCaseCheckBox); leftLayout->addWidget(m_pQBackwardCheckBox); QVBoxLayout *rightLayout = new QVBoxLayout; rightLayout->addWidget(m_pQFindButton); rightLayout->addWidget(m_pQCloseButton); rightLayout->addStretch(); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addLayout(leftLayout); mainLayout->addLayout(rightLayout); setLayout(mainLayout); setWindowTitle(tr("Find")); setFixedHeight(sizeHint().height()); } catch(std::bad_alloc& e) { std::cerr << e.what() << std::endl; } catch(...) { std::cerr << "err" << std::endl; } } FindDlg::~FindDlg() { if (NULL != m_pQLabel) { delete m_pQLabel; } if (NULL != m_pQLineEdit) { delete m_pQLineEdit; } if (NULL != m_pQCaseCheckBox) { delete m_pQCaseCheckBox; } if (NULL != m_pQBackwardCheckBox) { delete m_pQBackwardCheckBox; } if (NULL != m_pQFindButton) { delete m_pQFindButton; } if (NULL != m_pQCloseButton) { delete m_pQCloseButton; } } void FindDlg::findClicked() { QString text = m_pQLineEdit->text(); Qt::CaseSensitivity cs = m_pQCaseCheckBox->isChecked() ? Qt::CaseInsensitive : Qt::CaseInsensitive; if (m_pQBackwardCheckBox->isChecked()) { emit findPrevious(text, cs); } else { emit findNext(text, cs); } return; } void FindDlg::enableFindButton(const QString& text) { m_pQFindButton->setEnabled(!text.isEmpty()); return; }
代码第X行,“12”符号来表示快捷键,可以用来控制焦点。而在第14行设置了行编辑器作为标签的伙伴。所谓伙伴“buddy”,就是一个窗口部件,它可以在按下标签的快捷键时接收焦点。
通过setDefault(true)让Find按钮成为对话框的默认按钮。意为当用户按下Enter键时如同鼠标点击了“Find”按钮。
当用户单击Find按钮时,就会调用findClicked()槽。而该槽将会发射findPrevious()或findNext()信号。emit是Qt中的关键字,像其他QT扩展一样它也会被C++预处理器转换成标准的C++代码。
由于在创建这个对话框中的窗口部件和而已时使用的是new,所以需要写一个能调用delete的析构函数,以便可以删除所创建的每一个窗口部件和布局。但是这样做并不是必需的,因为QT会在删除父对象的时候自动删除其所属的子对象,也就会删除FindDialog中作为期子孙的所有子窗口部件和子布局。但是个人还是比较喜欢自己控制的东西。