第二章 创建对话框

1、子类化QDialog

第一个例子是完全使用C++编写的Find对话框。

finddialog.h:

 1 #ifndef FINDDIALOG_H
 2 #define FINDDIALOG_H
 3 
 4 #include <QDialog>
 5 
 6 class QCheckBox;
 7 class QLabel;
 8 class QLineEdit;
 9 class QPushButton;
10 
11 class FindDialog : public QDialog
12 {
13     Q_OBJECT
14 public:
15     FindDialog(QWidget *parent = 0);
16 signals:
17     void findNext(const QString &str, Qt::CaseSensitivity cs);
18     void findPrevious(const QString &str, Qt::CaseSensitivity cs);
19 private slots:
20     void findClicked();
21     void enableFindButton(const QString &text);
22 private:
23     QLabel *label;
24     QLineEdit *lineEdit;
25     QCheckBox *caseCheckBox;
26     QCheckBox *backwardCheckBox;
27     QPushButton *findButton;
28     QPushButton *closeButton;
29 };
30 
31 #endif // FINDDIALOG_H

头部的预编译指令是为了防止对这个头文件的多重包含

对于定义了信号与槽的类来说在类定义的开始处的Q_OBJECT宏都是必须的,它给出了一些函数的声明

FindDialog类的构造函数是典型的Qt窗口部件类的定义方式。parent参数指定了它的父窗口部件。该参数的默认值是一个空指针,意味着该对话框没有父对象。

signals关键字实际上是一个宏,C++预处理器会在编译程序找到它之前把它转换成标准C++代码。我的疑问是为什么槽的声明是私有的

finddialog.cpp:

 1 #include <QtGui>
 2 #include <QLabel>
 3 #include <QCheckBox>
 4 #include <QLineEdit>
 5 #include <QPushButton>
 6 #include <QHBoxLayout>
 7 #include <QVBoxLayout>
 8 #include "finddialog.h"
 9 
10 FindDialog::FindDialog(QWidget *parent)
11     :QDialog(parent)
12 {
13     label = new QLabel(tr("Find &what:"));
14     lineEdit = new QLineEdit;
15     label->setBuddy(lineEdit);
16 
17     caseCheckBox = new QCheckBox(tr("Match &case"));
18     backwardCheckBox = new QCheckBox(tr("Search &backward"));
19 
20     findButton = new QPushButton(tr("&Find"));
21     findButton->setDefault(true);
22     findButton->setEnabled(false);
23 
24     closeButton = new QPushButton("Close");
25     connect(lineEdit, SIGNAL(textChanged(const QString &)),
26             this, SLOT(enableFindButton(const QString &)));
27     connect(findButton, SIGNAL(clicked()),
28             this, SLOT(findClicked()));
29     connect(closeButton, SIGNAL(clicked()),
30             this, SLOT(close()));
31 
32     QHBoxLayout *topLeftLayout = new QHBoxLayout;
33     topLeftLayout->addWidget(label);
34     topLeftLayout->addWidget(lineEdit);
35 
36     QVBoxLayout *leftLayout = new QVBoxLayout;
37     leftLayout->addLayout(topLeftLayout);
38     leftLayout->addWidget(caseCheckBox);
39     leftLayout->addWidget(backwardCheckBox);
40 
41     QVBoxLayout *rightLayout = new QVBoxLayout;
42     rightLayout->addWidget(findButton);
43     rightLayout->addWidget(closeButton);
44     rightLayout->addStretch();
45 
46     QHBoxLayout *mainLayout = new QHBoxLayout;
47     mainLayout->addLayout(leftLayout);
48     mainLayout->addLayout(rightLayout);
49     setLayout(mainLayout);
50 
51     setWindowTitle(tr("Find"));
52     setFixedHeight(sizeHint().height());
53 }
54 
55 void FindDialog::findClicked()
56 {
57     QString text = lineEdit->text();
58     Qt::CaseSensitivity cs =
59             caseCheckBox->isChecked() ? Qt::CaseSensitive
60                                       : Qt::CaseInsensitive;
61     if(backwardCheckBox->isChecked())
62     {
63         emit findPrevious(text, cs);
64     }
65     else
66     {
67         emit findNext(text, cs);
68     }
69 }
70 
71 void FindDialog::enableFindButton(const QString &text)
72 {
73     findButton->setEnabled(!text.isEmpty());
74 }

在字符串周围的tr函数调用时把它们翻译成其他语言的标记,即使现在没有需要将程序翻译成其它语言,但是这样做也是有好处的。

在部件的text字符创中使用了符号“&”表示快捷键,使用alt+“&”后的第一个字母可以实现快捷的选中该部件。

所谓buddy,就是一个窗口部件,它可以再按下标签的快捷键时接受焦点输入。

setDefault让Find按钮称为默认按钮,默认按钮即当用户按下回车时能够按下对应的键。

omit是Qt中的关键字,它会被C++预处理器转换成标准C++代码。

main.cpp:

 1 #include <QApplication>
 2 #include "finddialog.h"
 3 
 4 int main(int argc, char** argv)
 5 {
 6     QApplication app(argc, argv);
 7     FindDialog *dialog = new FindDialog;
 8     dialog->show();
 9     return app.exec();
10 }

运行效果:

2、深入介绍槽与信号

信号与槽是Qt编程的基础。它可以让编程人员将这些互不了解的对象绑定在一起。

槽和普通的C++函数几乎是一样的,可以使虚函数、可以被重载、可以使公有的、保护的、私有的。并且也可以被其他C++成员函数直接调用,还有它们的参数可以使任意类型,唯一不同的是:槽还可以和信号连接在一起,在这种情况下,每当发射这个信号的时候,就会自动调用这个槽。

connect(sender, SIGNAL(signal), receiver,SLOT(slot));

这里的sender和receiver是指向QObject的指针,signal和slot是不带参数的函数名。实际上,SIGNAL和SLOT宏会把它们的参数转换成相应的字符串。

  • 一个信号可以连接多个槽

在发射这个信号的时候会以不确定的顺序一个接一个的调用这些槽

  • 多个信号可以连接同一个槽

无论发射哪一个信号都会调用这个槽

  • 一个信号可以与另外一个信号连接

当发射第一个信号的时候也会发射第二个信号

  • 连接可以被移除

这种情况很少用

注意:要把信号连接到槽,它们的参数必须具有相同的顺序和相同的类型。例外:如果信号比连接的槽的参数多,那么后面多余的参数将被忽略。

3、快速设计对话框

这一节会使用Qt Designer来可视化的设计一个对话框。

操作步骤就是使用Qt Designer来设计需要的对话框,然后保存为.ui的格式。

在编译的时候会将.ui格式的文件转换为C++并且存储在ui_name.h和ui_name.cpp中。

生成的类没有任何基类,当在程序中使用它时,可以创建一个QDialog类的对象,然后把它传递给setupUi()函数。

现在定义一个新的类继承自QDialog和Ui::GoToCellDialog类(我填写的Ui文件生成的类名)。

gotocelldialog.h:

 1 #ifndef GOTOCELLDIALOG_H
 2 #define GOTOCELLDIALOG_H
 3 
 4 #include <QDialog>
 5 #include "ui_gocelldialog.h"
 6 
 7 class GotoCellDialog : public QDialog, public Ui::GoToCellDialog
 8 {
 9     Q_OBJECT
10 public:
11     GotoCellDialog(QWidget *parent = 0);
12 private slots:
13     void on_lineEdit_textChanged();
14 };
15 
16 #endif // GOTOCELLDIALOG_H

该类继承自两个类:QDialog、Ui::GoToCellDialog

gotocelldialog.cpp:

 1 #include <QtGui>
 2 #include "gotocelldialog.h"
 3 
 4 GotoCellDialog::GotoCellDialog(QWidget *parent)
 5     : QDialog(parent)
 6 {
 7     setupUi(this);
 8 
 9     // QRegExp regExp("[A-Za-z][1-9][0-9]{0, 2}");
10     QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
11     lineEdit->setValidator(new QRegExpValidator(regExp, this));
12 
13     connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
14     connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
15 }
16 
17 void GotoCellDialog::on_lineEdit_textChanged()
18 {
19     okButton->setEnabled(lineEdit->hasAcceptableInput());
20 }

实现文件中绑定了需要绑定的信号与槽。

对编辑框的输入进行了验证,使用正则表达式的方法来验证。

accept()槽可以讲对话框返回的结果变量设置为QDialog::Accepted,其值为1、而reject()槽会把对话框的值设置为QDialog::Rejected,其值为0。可以根据对话框的返回值来判断是否点击了OK按钮。

main.cpp:

 1 #include <QApplication>
 2 
 3 #include "gotocelldialog.h"
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     QApplication a(argc, argv);
 8 
 9     GotoCellDialog *dialog = new GotoCellDialog;
10     dialog->show();
11 
12     return a.exec();
13 }

实例化一个该类的对象并显示出来。

使用QDialogButtonBox来制作这个对话框,以使它在MAC平台上显得更加圆润。

4、

原文地址:https://www.cnblogs.com/lit10050528/p/3872811.html