zoukankan      html  css  js  c++  java
  • 第八章 Qt GUI之对话框使用

    第八章 Qt GUI之对话框使用

    对话框可以是模态(modal)的或非模态(modeless)两种。当我们在一个用户界面程序里面对一个对话框(比如选择文件对话框)的操作没有结束前,界面的其他窗口无法操作,遇到的这个对话框就是模态对话框,而当我们在一个字处理软件中利用查找和替换对话框时,可以在字处理软件和查找替换对话框之间切换进行交互,这就是个非模态对话框。

    先来看一下QDialog类的继承关系,如下图所示。

     

     QDialog从QWidget继承,然后它下面又被Qt的内置对话框类(QFileDialog选择文件或目录对话框、QFontDialog选择字体对话框、QMessageBox消息提示对话框等)继承。用户要实现自己的对话框,需要继承自QDialog类,并包含头文件<QDialog>。

    一、快速设计对话框

    例子1:

    实现一个Find(查找对话框),它的运行效果如下图所示,这将实现一个拥有自主权的对话框。

    程序清单如下:

    finddialog.h

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

    finddialog.cpp:

     1 #include <QtGui>
     2 #include "finddialog.h"
     3 
     4 FindDialog::FindDialog(QWidget *parent)
     5     : QDialog(parent)
     6 {
     7     label = new QLabel(tr("Find &what")); //tr()函数是把它们翻译成其他语言的标志,“&”来表示快捷键(Alt+W)
     8     lineEdit = new QLineEdit;
     9     label->setBuddy(lineEdit);//设置行编辑器为标签的伙伴,按下标签的快捷键(Alt+W)时接收焦点,焦点会移动到行编辑器
    10 
    11     caseCheckBox = new QCheckBox(tr("Math &case"));
    12     backwardCheckBox = new QCheckBox(tr("Search &backward"));
    13 
    14     findButton = new QPushButton(tr("&Find"));
    15     findButton->setDefault(true);//设置“Find”按钮为默认按钮,默认按钮就是当用户Enter键时能够按下对应的按钮
    16     findButton->setEnabled(false);//禁用“Find”按钮,它通常显示为灰色,不能和用户进行交互操作
    17 
    18     closeButton = new QPushButton(tr("Close"));
    19 
    20     connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(enableFindButton(const QString &)));
    21     connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
    22     connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
    23 
    24     QHBoxLayout *topLeftLayout = new QHBoxLayout;
    25     topLeftLayout->addWidget(label);
    26     topLeftLayout->addWidget(lineEdit);
    27 
    28     QVBoxLayout *leftLayout = new QVBoxLayout;
    29     leftLayout->addLayout(topLeftLayout);
    30     leftLayout->addWidget(caseCheckBox);
    31     leftLayout->addWidget(backwardCheckBox);
    32 
    33     QVBoxLayout *rightLayout = new QVBoxLayout;
    34     rightLayout->addWidget(findButton);
    35     rightLayout->addWidget(closeButton);
    36     rightLayout->addStretch();
    37 
    38     QHBoxLayout *mainLayout = new QHBoxLayout;
    39     mainLayout->addLayout(leftLayout);
    40     mainLayout->addLayout(rightLayout);
    41     setLayout(mainLayout); //将mainLayout布局安装在FindDialog
    42 
    43     setWindowTitle(tr("Find"));
    44     setFixedHeight(sizeHint().height());
    45 }
    46 
    47 void FindDialog::findClicked()
    48 {
    49     QString text = lineEdit->text();
    50     Qt::CaseSensitivity cs = caseCheckBox->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive;
    51     if (backwardCheckBox->isChecked())
    52     {
    53         emit findPrevious(text, cs);
    54     }
    55     else
    56     {
    57         emit findNext(text, cs);
    58     }
    59 }
    60 
    61 void FindDialog::enableFindButton(const QString &text)
    62 {
    63     findButton->setEnabled(!text.isEmpty());
    64 }
    65 
    66 FindDialog::~FindDialog()
    67 {
    68     
    69 }

    main.cpp

    #include <QApplication>
    #include "finddialog.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        FindDialog *w = new FindDialog;
        w->show();
        
        return a.exec();
    }

    编译运行就出现上图效果了。

    例子2:

    使用Qt designer设置对话框,实现效果如下图:

    基本步骤:

    1、创建并初始化子窗口部件;

    2、把子窗口部件放在布局中;

    3、设置Tab键顺序;

    4、建立信号-槽之间的连接;

    5、实现对话框的自定义槽。

    第一步是创建子窗口部件并且把它们放置到窗体中。创建一个标签(Label)、一个行编辑器(Line Edit)、一个水平分隔符(Horizontal Spacer)、两个按钮(Push Button)。

    使用Qt设计师的属性编辑器设置每个窗口部件的属性:

    1、单击文本标签。确保此时objectName的属性是“label”,将它的text属性设置成“&Cell Location”。

    2、单击行编辑器。确保objectName属性是“lineEdit”。

    3、单击第一个按钮。将它的objectName属性设置成“okButton”,将它的enabled属性设置成“false”,将它的text属性设置成“OK”,并且把它的default属性设置成“true”。

    4、单击第二个按钮。将它的objectName属性设置成“cancelButton”,并且将它的text属性设置成“Cancel”。

    5、单击这个窗体中空白的地方,选中窗体本身。将它的windowTitle属性设置成“Go to Cell”。

    6、单击Edit->Edit Buddies进入一种允许设置窗口部件伙伴(buddy)的特殊模式。然后,单击这个标签并把红色箭头拖到行编辑器上,释放鼠标按键。单击Edit->Edit Widgets离开伙伴设置模式。

    下一步是在窗体中摆放这些窗口部件,步骤如下:

    1、单击“Cell Location”标签并且按下ctrl键是单击与之相邻的行编辑器,这样就可以同时选择了它们,然后选择水平布局(Lay Out Horizontally)。

    2、选中分隔符、OK按钮和Cancel按钮,然后选择水平布局(Lay Out Horizontally)。

    3、单击窗体中的空白,取消对所有已选中项的选择,然后单击垂直布局(Lay Out Vertically)。

    4、单击Edit->Edit Tab Order。在每一个可以接受焦点的窗口部件上,都会出现一个带蓝色矩形的数字,如下图所示。按照你所希望的接受焦点的顺序单击每一个窗口部件,然后单击Edit->Edit Widgets离开Tab键顺序设置模式。

    接下来添加代码:

    main.cpp

     1 #include <QApplication>
     2 #include "mywidget.h"
     3 
     4 int main(int argc, char *argv[])
     5 {
     6     QApplication a(argc, argv);
     7     MyDialog w;
     8     w.show();
     9     
    10     return a.exec();
    11 }

    mywidget.h

     1 #ifndef MYWIDGET_H
     2 #define MYWIDGET_H
     3 
     4 #include <QDialog>
     5 
     6 namespace Ui {
     7 class MyDialog;
     8 }
     9 
    10 class MyDialog : public QDialog
    11 {
    12     Q_OBJECT
    13     
    14 public:
    15     explicit MyDialog(QDialog *parent = 0);
    16     ~MyDialog();
    17 
    18 private slots:
    19     void on_lineEdit_textChanged();
    20     
    21 private:
    22     Ui::MyDialog *ui;
    23 };
    24 
    25 #endif // MYWIDGET_H

    mywidget.cpp

     1 #include "mywidget.h"
     2 #include "ui_mywidget.h"
     3 
     4 MyDialog::MyDialog(QDialog *parent) :
     5     QDialog(parent),
     6     ui(new Ui::MyDialog)
     7 {
     8     ui->setupUi(this);
     9 
    10     QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");//建立一个正则表达式
    11     ui->lineEdit->setValidator(new QRegExpValidator(regExp, this)); //检验器限制输入的范围,
    12                                                                     //Qt提供3个内置检验器类:QIntValidator、QDoubleValidator、QRegExpValidator
    13 
    14     connect(ui->okButton, SIGNAL(clicked()), this, SLOT(accept())); //accept()槽函数关闭对话框,将对话框返回的结果变量设置为QDialog::Accepted(其值为1)
    15     connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(reject()));//reject()槽函数关闭对话框,将对话框返回的结果变量设置为QDialog::Reject(其值为0)
    16 }
    17 
    18 void MyDialog::on_lineEdit_textChanged()
    19 {
    20     ui->okButton->setEnabled(ui->lineEdit->hasAcceptableInput());
    21 }
    22 
    23 MyDialog::~MyDialog()
    24 {
    25     delete ui;
    26 }

    最后点击编译运行就ok了。

    二、可扩展的对话框

    这部分内容直接截取别人的,不想写。

    前面我们设计的对话框都是不能改变它的样子的。但是有时需要对话框根据要求进行适当的改变。两个最常用的需要改变的对话框是可扩展对话框和多页对话框。这两种类型的可以通过代码编写,也可以用Qt Designer设计。一个例子如下图所示:

    可扩展对话框通常外观简单,带有一个可扩展按钮来切换对话框的简单外观和可扩展外观。这种对话框通常为了迎合普通用户和高端用户而设计的,如果没有特别请求隐藏高级应用部分。在这个实验中,我们使用 Qt Designer设计一个可扩展对话框。

    对话框是一个表格程序的排序对话框,对用户选择的一些列按要求排列。对话框的简单外观允许用户输入一个简单排序关键词,扩展部分允许输入两个额外的排序关键词。一个More按钮使用户在简单外观和扩展外观进行切换。

    我们使用 Qt Designer创建这个可扩展的对话框,在运行时刻隐藏高级功能,这个看起来很复杂的对话框用Qt Designer可以很容易实现。首先设计好第一个关键词,第二个和第三个关键词通过复制就可以得到:

    1、 启动“文件”?“新建”菜单,选择“Dialog without Buttons”模板。

    2、 拖动一个PushButton按钮并把它拖放到窗体的右上角。将它的objectName修改为“okButton”,并将它的default属性设置为“true”,将它的text属性设置为“确定”,这就创建了OK按钮。

    3、 同样的办法创建Cancel按钮,放到OK按钮的下方,将objectName修改为“cancelButton”,将text属性设置为“取消”。

    4、 创建一个垂直分隔符(Vertical Spacer)并将它放到Cancel按钮的下方,然后再创建一个More按钮,并将它放在垂直分隔符的下方,将More按钮的objectName修改为“moreButton”,text属性设置为“(&M)更多”,checkable属性设置为“true”。

    5、 选择OK按钮,Cancel按钮,垂直分隔符和More按钮,将它们的布局设定为“垂直布局”。

    6、 创建一个群组框(GroupBox),两个标签(Label),两个下拉组合框(Combo Box)和一个水平分隔符(Horizontal Spacer),先把它们放在对话框的任何地方。

    7、 拖动群组框的右下角,把它拖动变大些,把上一步中其他控件移动到群组框中,按比例调整位置。当你按住鼠标左键将其他部件拖动到群组框内的时候,应该在群组框显示出灰色的时候才松开鼠标,否则,有可能部件只是挨着群组框并没有正确的放入其中。

    8、 拖动第二个下拉组合框,将其宽度调整为第一个下拉框的二倍左右。现在看起来的情况大概如下图所示:

    9、 将群组框的title属性设置为“&Primary Key”,第一个标签的text属性设置为“Column:”,

    第二个标签的text属性为“Order:”。

    10、 右键单击第一个组合框,从Qt设计师弹出的右键菜单的组合框编辑器中选择“编辑项目”,

    用文本“None”创建一个项目。

    11、同样的方式对第二个组合框创建两个项目,项目为“Ascending”和“Descending”两个项目,

    即升序和降序排列。

    12、右键单击群组框,然后选择“布局”?“栅格布局”。再次右键单击群组框,并选择“布局”

    ->“调整大小”,这个操作也可以通过单击工具栏上的按钮“”来完成,产生的布局如上图2的右图所示布局。

    如果设计过程中出现错误,可以选择 “编辑”?“撤销”或者“打破布局”工具按钮,重新进行布局。当然只要看起来不是很难看,也可以是其他的样子,只要易于理解就是ok。

    现在加入其它两个群组框:Secondary Key和Teriary Key:

    1、将对话框拖动到足够大,以便能容纳下另外两个部分。

    2、复制第一个组合框,粘贴两次,依次拖动到下面。

    3、把复制的两个组合框的title属性为“&Secondary Key”和“&Tertiary Key”。

    4、创建一个垂直分隔符(Vertical Spacer),并将它放在Primary Key群组框和Secondary Key群组框的中间。

    5、适当调整添加的控件的位置。

    6、选择对话框中的所有控件,降它们的布局设置为“栅格布局”,得到的效果应该如下图3(a)。

    7、单击窗体,取消对窗口中任意控件的选择,将整个对话框窗体的布局设置为“栅格布局”。然后向上和向左拖动窗体的右下角,将窗体变得尽可能小,设置两个垂直空白的sizeHint属性为[20,0]。现在窗体应该像下图3(b)所示:

    最终的网格布局是4行2列,一共有8个单元格。如果你做出来的不是这样,那么请撤销布局,重新进行布局。

    按照下图命名每一个控件。命名对话框为 SortDialog,窗口标题为“Sort”。对各个控件进行命名,也就是修改控件的objectName属性,最终结果如下图4:

    设置Tab顺序,从上到下点击下拉框,然后点击Ok,Cancel,More按钮。最终的顺序如下图(a):

    以上是对话框的设计。然后用 Qt Designer建立控件的信号连接,单击工具栏上的(即编辑信号/槽),切换到信号/槽的编辑状态。将“确认”和“取消”按钮连接到对话框的accept()和reject()槽函数。操作方法是点击“确认按钮”并拖动到对话框的空白处即可,然后在弹出的对话框中左边点选clicked()信号,右边点选accept()槽函数,如上图(b)所示。同样的方法将“取消”按钮连接到reject()槽函数。

    然后连接“更多”按钮和secondaryGroupBox群组框,将按钮的toggled(bool)信号和群组框的setVisible(bool)槽函数连接。同样将“更多”按钮与tertiaryGroupBox群组框setVisible(bool)槽函数连接。在连接的时候,可能看不到群组框的setVisible(boo)槽函数,这时在连接对话框(图5(b))中点选“显示从QWidget继承的信号和槽”即可看到。

    最终的连接情况如下图6所示,我们可以在“信号/槽编辑器”中清楚地看到连接情况。

    创建一个 sort目录,将对话框保存到sort目录下,文件名为:sortdialog.ui。

    下面给这个窗体添加代码,我们使用多继承的方式使用这个对话框,也就是创建一个新的类来继承QDialog类和这个窗体的类。

    首先新建一个sortdialog.h头文件,代码如下:

    然后新建sortdialog.cpp源文件:

     1 #include <QtGui>
     2 #include "sortdialog.h"
     3 SortDialog::SortDialog(QWidget *parent):QDialog(parent)
     4 {
     5 setupUi(this);
     6 secondaryGroupBox->hide();
     7 tertiaryGroupBox->hide();
     8 layout()->setSizeConstraint(QLayout::SetFixedSize);
     9 setColumnRange('A', 'Z');
    10 }
    11 void SortDialog::setColumnRange(QChar first, QChar last)
    12 {
    13 primaryColumnCombo->clear();
    14 secondaryColumnCombo->clear();
    15 tertiaryColumnCombo->clear();
    16 secondaryColumnCombo->addItem(tr("None"));
    17 tertiaryColumnCombo->addItem(tr("None"));
    18 primaryColumnCombo->setMinimumSize(secondaryColumnCombo->sizeHint());
    19 QChar ch = first;
    20 while (ch <= last) {
    21 primaryColumnCombo->addItem(QString(ch));
    22 secondaryColumnCombo->addItem(QString(ch));
    23 tertiaryColumnCombo->addItem(QString(ch));
    24 ch = ch.unicode() + 1;
    25 }
    26 }

    在构造函数中,隐藏了secondaryGroupBox和tertiaryGroupBox群组框部分。并设置对话框的sizeConstraint的属性为QLayout::setFixedSize,这样用户不能随便改变对话框的大小。

    下面是main.cpp文件:

    编译运行这个程序,点击“更多”按钮,查看对话框的改变,结果应该与图1一样。另一种可以改变的对话框是多页对话框。这类对话框也可以用两种方式创建。相关的类有QTabWidget,QStackedWidget,QListWidget,QTreeWidget等。

  • 相关阅读:
    【资料整理】面向对象
    【资料整理】函数(方法)
    【资料整理】数组
    【资料整理】循环、判断、三元表达式
    【资料整理】类型转换、运算符
    【资料整理】c#基础
    线性表的链式表示和实现
    线性表
    PAT 乙级1062最简分数
    HDU 1027(全排列)
  • 原文地址:https://www.cnblogs.com/heguoyuan/p/4280336.html
Copyright © 2011-2022 走看看