一 基础窗口部件QWidget

QWidget是所有用户界面对象的基类,被称为基础窗口部件。QWidget继承自QObject类和QPaintDevice类,其中QObject类是所有支持Qt对象模型的基类,QPaintDevice类是所有可以绘制对象的基类。

1.1 窗口,子部件以及窗口类型

// 新建QWidget类对象,默认parent参数是0,所以它是个窗口
QWidget *widget = new QWidget();
// 设置窗口标题
widget->setWindowTitle(QObject::tr("我是widget")); 
// 新建QLabel对象,默认parent参数是0,所以它是个窗口
QLabel *label = new QLabel();
label->setWindowTitle(QObject::tr("我是label"));
// 设置要显示的信息
label->setText(QObject::tr("label:我是个窗口"));   
// 改变部件大小,以便能显示出完整的内容
label->resize(180, 20);  
// label2指定了父窗口为widget,所以不是窗口
QLabel *label2 = new QLabel(widget);
label2->setText(QObject::tr("label2:我不是独立窗口,只是widget的子部件"));
label2->resize(250, 20);
// 在屏幕上显示出来
label->show();       
widget->show();

在这里插入图片描述

  • 在程序中定义了一个QWidget类对象的指针widget和两个QLabel对象指针label与label2,其中label没有父窗口,而label2在widget中,widget是其父窗口。

  • 窗口部件(Widget)这里简称部件,是Qt中建立用户界面的主要元素。像主窗口、对话框、标签、还有按钮、文本输入框等都是窗口部件。

  • 在Qt中,把没有嵌入到其他部件中的部件称为窗口,一般的,窗口都有边框和标题栏,就像程序中的widget和label一样。

  • QMainWindow和大量的QDialog子类是最一般的窗口类型。窗口就是没有父部件的部件,所以又称为顶级部件(top-level widget)。与其相对的是非窗口部件,又称为子部件(child widget)。在Qt中大部分部件被用作子部件,它们嵌入在别的窗口中,例如程序中的label2。

1.2 窗口类型

QWidget的构造函数有两个参数:QWidget * parent = 0和Qt::WindowFlags f = 0;
前面的parent就是指父窗口部件,默认值为0,表明没有父窗口;
而后面的f参数是Qt::WindowFlags类型的,它是一个枚举类型,分为窗口类型(WindowType)和窗口标志(WindowFlags。前者可以定义窗口的类型,比如我们这里f=0,表明使用了Qt::Widget一项,这是QWidget的默认类型,这种类型的部件如果有父窗口,那么它就是子部件,否则就是独立的窗口。

  • 例如:使用其中的Qt::Dialog和Qt::SplashScreen,更改程序中的新建对象的那两行代码:
    QWidget *widget = new QWidget(0, Qt::Dialog);
    QLabel *label = new QLabel(0, Qt::SplashScreen);
  • 当更改窗口类型后,窗口的样式发生了改变,一个是对话框类型,一个是欢迎窗口类型。
  • 而对于窗口标志,它主要的作用是更改窗口的标题栏和边框,而且它们可以和窗口类型进行位或操作。下面再次更改那两行代码:
    QWidget *widget = new QWidget(0, Qt::Dialog | Qt::FramelessWindowHint);
    QLabel *label = new QLabel(0, Qt::SplashScreen | Qt::WindowStaysOnTopHint);
    Qt::FramelessWindowHint用来产生一个没有边框的窗口,而Qt::WindowStaysOnTopHint用来使该窗口停留在所有其它窗口上面。
    在这里插入图片描述

1.3 窗口几何部件

对于窗口的大小和位置,根据是否包含边框和标题栏两种情况,要用不同的函数来获取它们的数值。
在这里插入图片描述
这里的函数分为两类,一类是包含框架的,一类是不包含框架的:
包含框架:x()、y()、frameGeometry()、pos()和move()等函数;
不包含框架:geometry()、width()、height()、rect()和size()等函数。

二 对话框QDialog

2.1 模态和非模态对话框

模态对话框就是在我们没有关闭它之前,不能再与同一个应用程序的其他窗口进行交互,比如新建项目时弹出的对话框。要想使一个对话框成为模态对话框,只需要调用它的exec()函数:

QDialog dialog(this);
dialog.exec();

而对于非模态对话框,既可以与它交互,也可以与同一程序中的其他窗口交互,例如Microsoft Word中的查找替换对话框。要使一个对话框成为非模态对话框,我们就可以使用new操作来创建,然后使用show()函数来显示。

QDialog *dialog = new QDialog(this);
dialog->show();

使用show()函数也可以建立模态对话框,只需在其前面使用setModal()函数即可。例如:

QDialog *dialog = new QDialog(this);
dialog->setModal(true);
dialog->show();

现在运行程序,可以看到生成的对话框是模态的。但是,它与用exec()函数时的效果是不一样的。这是因为调用完show()函数后会立即将控制权交给调用者,那么程序可以继续往下执行。而调用exec()函数却不是这样,它只有当对话框被关闭时才会返回。
与setModal()函数相似的还有一个setWindowModality()函数,它有一个参数来设置模态对话框要阻塞的窗口类型,可以是:
Qt::NonModal(不阻塞任何窗口,就是非模态),
Qt::WindowModal(阻塞它的父窗口和所有祖先窗口以及它们的子窗口),
Qt::ApplicationModal(阻塞整个应用程序的所有窗口)。
而setModal()函数默认设置的是Qt::ApplicationModal。

2.2 对窗口切换

2.2.1信号和槽

在Qt中使用信号和槽机制来完成对象之间的协同操作。
简单来说,信号和槽都是函数,比如按下窗口上的一个按钮后想要弹出一个对话框,那么就可以将这个按钮的单击信号和我们定义的槽关联起来,在这个槽中可以创建一个对话框,并且显示它。这样,当单击这个按钮时就会发射信号,进而执行我们的槽来显示一个对话框。
方法一:使用connect()连接
在mywidget.h中添加

public slots:
void showChildDialog();

在mywidget.cpp文件中将槽的实现 :

void MyWidget::showChildDialog()
{
    QDialog *dialog = new QDialog(this);
    dialog->show();
}

在mywidget.cpp文件的MyWidget类的构造函数中使用connect()关联按钮单击信号和自定义的槽如下:

connect(ui->showChildButton, &QPushButton::clicked,
            this, &MyWidget::showChildDialog);

方法二:在设计模式中添加
在设计模式中向窗口上添加两个Push Button,并且分别更改其显示文本为“进入”和“退出”。点击设计器上方的“编辑信号/槽”图标,或者按下快捷键F4,这时便进入了部件的信号和槽的编辑模式。在“退出程序”按钮上按住鼠标左键,然后拖动到窗口界面上,这时松开鼠标左键。
在弹出的配置连接对话框中,选中下面的“显示从QWidget继承的信号和槽”选项,然后在左边的QPushButton栏中选择信号clicked(),在右边的QDialog栏中选择对应的槽close(),完成后按下“确定”。

在这里插入图片描述
方法三:自动关联
在“进入”按钮上右击,在弹出的菜单上选择“转到槽”,然后在弹出的对话框中选择clicked()信号,并按“确定”。这时便会进入代码编辑模式,并且定位到自动生成的on_pushButton_clicked()槽中。在其中添加代码:

void MyDialog::on_pushButton_clicked()
{    accept();   } 

在这里插入图片描述

2.3 标准对话框

Qt提供了一些常用的对话框类型,它们全部继承自QDialog类,并增加了自己的特色功能,比如获取颜色、显示特定信息等。
颜色对话框
文件对话框
字体对话框
输入对话框
消息对话框
进度对话框
错误信息对话框
向导对话框
设计界面直接右键转到槽。(clicked())
在这里插入图片描述
在这里插入图片描述
mywidget.cpp中头文件

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>
#include <QColorDialog>
#include <QFileDialog>
#include <QFontDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QProgressDialog>
#include <QErrorMessage>

构造函数中添加

errordlg = new QErrorMessage(this);

颜色对话框

void myWidget::on_pushButton_clicked()
{
    //  QColor color = QColorDialog::getColor(Qt::red, this, tr("颜色对话框"),
    //QColorDialog::ShowAlphaChannel);
    QColorDialog dialog(Qt::red, this);                // 创建对象
    dialog.setOption(QColorDialog::ShowAlphaChannel); // 显示alpha选项
    dialog.exec();                                    // 以模态方式运行对话框
    QColor color = dialog.currentColor();             // 获取当前颜色
    qDebug() << "color: " << color;
}

文件对话框

void myWidget::on_pushButton_2_clicked()
{
    //    QString fileName = QFileDialog::getOpenFileName(this, tr("文件对话框"),"D:", tr("图片文件(*png *jpg);;文本文件(*txt)"));
    //qDebug() << "fileName:" << fileName;
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("文件对话框"),
                                                          "D:", tr("图片文件(*png *jpg)"));
    qDebug()<< "fileNames:" << fileNames;
}

字体对话框

void myWidget::on_pushButton_4_clicked()
{
    // ok用于标记是否按下了“OK”按钮
    bool ok;
    QFont font = QFontDialog::getFont(&ok, this);
    // 如果按下“OK”按钮,那么让“字体对话框”按钮使用新字体
    // 如果按下“Cancel”按钮,那么输出信息
    if (ok) ui->pushButton_3->setFont(font);
    else qDebug() << tr("没有选择字体!");
}

输入对话框

void myWidget::on_pushButton_3_clicked()
{
    bool ok;
    // 获取字符串
    QString string = QInputDialog::getText(this, tr("输入字符串对话框"),
                                           tr("请输入用户名:"), QLineEdit::Normal,tr("admin"), &ok);
    if(ok) qDebug() << "string:" << string;
    // 获取整数
    int value1 = QInputDialog::getInt(this, tr("输入整数对话框"),
                                      tr("请输入-1000到1000之间的数值"), 100, -1000, 1000, 10, &ok);
    if(ok) qDebug() << "value1:" << value1;
    // 获取浮点数
    double value2 = QInputDialog::getDouble(this, tr("输入浮点数对话框"),
                                            tr("请输入-1000到1000之间的数值"), 0.00, -1000, 1000, 2, &ok);
    if(ok) qDebug() << "value2:" << value2;
    QStringList items;
    items << tr("条目1") << tr("条目2");
    // 获取条目
    QString item = QInputDialog::getItem(this, tr("输入条目对话框"),
                                         tr("请选择或输入一个条目"), items, 0, true, &ok);
    if(ok) qDebug() << "item:" << item;
}

消息对话框

void myWidget::on_pushButton_6_clicked()
{
    // 问题对话框
    int ret1 = QMessageBox::question(this, tr("问题对话框"),
                                     tr("你了解Qt吗?"), QMessageBox::Yes, QMessageBox::No);
    if(ret1 == QMessageBox::Yes) qDebug() << tr("问题!");
    // 提示对话框
    int ret2 = QMessageBox::information(this, tr("提示对话框"),
                                        tr("这里是安庆师范大学!"), QMessageBox::Ok);
    if(ret2 == QMessageBox::Ok) qDebug() << tr("提示!");
    // 警告对话框
    int ret3 = QMessageBox::warning(this, tr("警告对话框"),
                                    tr("不能提前结束!"), QMessageBox::Abort);
    if(ret3 == QMessageBox::Abort) qDebug() << tr("警告!");
    // 错误对话框
    int ret4 = QMessageBox::critical(this, tr("严重错误对话框"),
                                     tr("发现一个严重错误!现在要关闭所有文件!"), QMessageBox::YesAll);
    if(ret4 == QMessageBox::YesAll) qDebug() << tr("错误");
    // 关于对话框
    QMessageBox::about(this, tr("关于对话框"),
                       tr("好好学习,不要再挂科了"));
}

进度对话框

void myWidget::on_pushButton_5_clicked()
{
    QProgressDialog dialog(tr("文件复制进度"), tr("取消"), 0, 50000, this);
    dialog.setWindowTitle(tr("进度对话框"));     // 设置窗口标题
    dialog.setWindowModality(Qt::WindowModal);  // 将对话框设置为模态
    dialog.show();
    for(int i=0; i<50000; i++) {                // 演示复制进度
        dialog.setValue(i);                     // 设置进度条的当前值
        QCoreApplication::processEvents();      // 避免界面冻结
        if(dialog.wasCanceled()) break;         // 按下取消按钮则中断
    }
    dialog.setValue(50000);    // 这样才能显示100%,因为for循环中少加了一个数
    qDebug() << tr("复制结束!");
}

错误信息对话框

void myWidget::on_pushButton_8_clicked()
{
    errordlg->setWindowTitle(tr("错误信息对话框"));
    errordlg->showMessage(tr("这里是出错信息!"));
}

向导页对话框

QWizardPage * myWidget::createPage1()  // 向导页面1
{
    QWizardPage *page = new QWizardPage;
    page->setTitle(tr("介绍"));
    return page;
}
QWizardPage * myWidget::createPage2()  // 向导页面2
{
    QWizardPage *page = new QWizardPage;
    page->setTitle(tr("用户选择信息"));
    return page;
}
QWizardPage * myWidget::createPage3()  // 向导页面3
{
    QWizardPage *page = new QWizardPage;
    page->setTitle(tr("结束"));
    return page;
}
void myWidget::on_pushButton_7_clicked()
{
    QWizard wizard(this);
    wizard.setWindowTitle(tr("向导对话框"));
    wizard.addPage(createPage1());     // 添加向导页面
    wizard.addPage(createPage2());
    wizard.addPage(createPage3());
    wizard.exec();
}

运行
在这里插入图片描述

三 总结

如何设置窗口类型,获取窗口信息的函数有哪些?
什么是信号和槽,有哪些关联方式?
Qt中标准对话框、常用部件有哪些?

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐