QT的UI应用程序设计

UI文件设计与运行机制

在VS2019中新建一个QT Widgets项目(如果有GUI项目可以创建GUI项目),选择QWidget作为窗体基类。
用VS创建的项目和QT Creater创建的项目文件目录稍有不同,下面来看看各个文件:

项目管理文件

后缀为.pro的文件是项目管理文件,用于记录一些设置。VS创建的项目没有.pro文件,这个步骤在VS创建项目的选项中就已经设置过了。
在这个文件中是可以后期添加各种QT模块的,在VS中如果要添加需要在扩展->Qt VS Tools->Qt Project Settings中设置。

界面文件

后缀为.ui的文件是可视化设计的窗体的定义文件,双击这个文件会打开Qt Designer对窗体进行可视化设计。
在这里插入图片描述
这个UI设计器具有以下功能区:

  • 左侧的Widget Box组件面板,界面设计的常见组件都可以在这里找到。
  • 中间区域是待设计的窗体。如果需要将某个组件放置到窗体上,直接从组件面板拖放即可。
  • 信号与槽编辑器和动作编辑器位于右下方,信号/槽编辑器用于可视化的进行信号与槽的关联,动作编辑器用于可视化设计动作。
  • 对象查看器:在右上方,用树状视图显示窗体上各个组件之间的布局包含关系。视图有两列,显示每个组件的对象名称和类名称。
  • 属性编辑器:在对象查看器下面,是界面设计常用到的编辑器。属性编辑器显示某个选中的组件或窗体的各个属性及其取值,可以在这里修改属性值。下面详细介绍这个编辑器:
  • 在这里插入图片描述
    在窗体上添加一个lable,点击这个lable观察这个属性编辑器。最上方显示的文字“lable:QLable”表示这个组件是一个QLable类型的组件。属性编辑器分为两列,分别为属性的名称和属性的值。可以看到属性分为了好几个组,其实这个分组表明了类的继承关系,QLable的继承关系是:“QObject”➡“QWidget”➡“QFrame”→“QLable”。
    QObjectName表明了这个组件对象的名称,界面上每个组件都需要唯一的对象名称以便被引用。
    设置其他属性值只需在这个编辑器内直接修改即可。

我们还可以添加一个按钮,让这个按钮点击后可以推出窗口。拖拽一个push button到窗口,在信号与槽工具栏中单击“➕”,在出现的条目中,发送者选择这个按钮,信号选择clicked(),接收者选择这个窗体,槽选择close(),这样设置表示按钮点击后执行Widget的close()函数。
在这里插入图片描述

主函数文件

main.cpp是实现main()函数的文件,内容如下:

#include "samp2_1.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv); //定义并创建应用程序
    samp2_1 w;  //定义并创建窗口
    w.show();  //显示窗口
    return a.exec(); //应用程序运行
}

窗体相关文件

头文件

在VS中项目的头文件和QT Creater中不太一样。简化了很多东西,但是其余必须的东西都没有变。

#pragma once

#include <QtWidgets/QWidget>
#include "ui_samp2_1.h"

class samp2_1 : public QWidget
{
    Q_OBJECT

public:
    samp2_1(QWidget *parent = Q_NULLPTR);

private:
    Ui::samp2_1Class ui;
};

Q_OBJECT这个宏很重要,这是使用Qt的信号槽机制都必须使用的一个宏。
剩下的就是构造函数

cpp文件

#include "samp2_1.h"

samp2_1::samp2_1(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
}

cpp文件实现了构造函数。构造函数只有一行语句ui->setupUi(this)它是执行了Ui:Widget类的setupUi()函数,这个函数实现窗口的生成与各种属性的设置、信号与槽的关联。

ui_项目名称.h文件

这个文件是对.ui文件编译生成后的一个文件,这个文件并不会自动添加到目录树中,可以手动添加现有项。这个文件并不需要我们手动修改,所有UI操作可以直接在QT Designer中设置,我们只是看看他做了什么操作:

  1. 定义自身的类,用于封装可视化设计的界面。
  2. 自动生成界面各个组件的成员变量定义。在public部分为每个组件都定义了一个指针变量,这个变量就是设置的变量名称objectName.
  3. 定义setupUi()函数。这个函数用于创建各个界面组件,并设置属性,设置信号与槽的关联。
  4. 定义namespace Ui,并定义一个从自身继承的类。

可视化UI设计

界面属性设置需要注意:

  1. objectName是窗体上创建的组件的实例名称,界面上每个组件都需要有一个唯一的objectName,程序访问界面组件都是通过其objectName访问的,自动生成的槽函数名称里也有objectName,所以组件的objectName需要在设计程序之前就设置好,之后不要改动。
  2. 不要在UI设计器里修改窗体的objectName,窗体的实例名称需要在使用窗体的代码中定义。

界面组件布局

QT的界面设计使用了布局(Layout)功能。布局就是组件的排列方式。使用布局可以使组件规则分布,并且随着窗体大小调整自身。

界面组件层次

我们会使用一些容器类,如QgoupBox、QtabWidget、QFrame等。可以把组件都放进一个容器中,移动这个容器将会移动内部所有组件。对象查看器中显示了各个组件之间的关系。

布局管理

UI设计器中,组件面板里有Layouts和Spacers两个组件面板,窗体上方的工具栏中也有布局管理按钮。
Layouts和spacers功能表:

布局组件功能
Vertical Layout垂直方向布局
Horizontal Layout水平方向布局
Grid Layout网格状布局,布局大小改变,每个网格大小都改变
Form Layout窗体布局,与网格布局相似,但是只有最右侧的网格改变大小
Horizontal Spacer一个用于水平分隔的空格
Vertical Spacer一个用于垂直分隔的空格

在设计窗口上方有个工具栏,用于调整计时器进入不同状态,以及进行布局设计,功能如下:
在这里插入图片描述

按钮功能
编辑窗口(F3)界面设计进入编辑状态,就是正常的设计状态
编辑信号/槽(F4)进入信号与槽的可视化设计状态
编辑伙伴进入伙伴编辑状态,可以设置一个label与一个组件成为伙伴关系
编辑tab顺序进入Tab顺序编辑状态,Tab顺序是在键盘上按Tab键时输入在焦点界面各组件之间的跳动顺序
水平布局(ctrl+H)将窗体上所选组件水平布局
垂直布局(ctrl+L)将窗体上所选组件垂直布局
使用分裂器水平布局将窗体上所选组件用一个分割条进行水平分割布局
使用分裂器垂直布局将窗体上所选组件用一个分割条进行垂直分割布局
栅格布局将窗体上所选组件按网格布局
窗体布局将窗体上所选组件按照窗体布局
打破布局解除窗体上所选组件的布局
调整大小自动调整所选组件的大小

使用工具栏布局按钮,只需要在窗体上选中需要设计布局的组件,然后点击某个布局按钮即可。
在窗体上选择组件时按住ctrl键可以实现组件多选。
选择某个容器类,相当于选择其中的所有组件。

我们还可以为整个窗体选择布局。不选中任何组件,选中窗体,点击工具栏中 的布局按钮。当窗体大小改变时,各个组件都会相应改变大小

伙伴关系与Tab

点击工具栏编辑伙伴会进入伙伴编辑状态。
伙伴关系指界面上一个Label和一个组件相关联。在伙伴编辑状态下,单击一个label,按住鼠标左键拖向一个组件,就建立了这个label和另一个组件之间的伙伴关系。
伙伴关系是为了在运行程序时,在窗体上用快捷键将焦点切换到某个组件上。

点击编辑Tab顺序进入Tab顺序编辑状态。Tab顺序是指在程序运行时,按键盘Tab键时焦点的移动顺序。

信号与槽

信号与槽是Qt编程的基础。

  • 信号(Signal)就是在特定情况下被发射的事件。GUI程序设计的主要内容就是对界面上各个组件的信号的响应。我们只需要知道什么情况下发射哪些信号,然后去响应这些信号就可以了。
  • 槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般C++函数是一样的,可以定义在类的任何部分,可以具有任何参数。也可以被直接调用。

信号与槽的关联是用==QObject::connect()==函数实现的:

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

参数分别为发射信号的对象;信号函数;接收信号的对象;槽函数。

SIGNAL和SLOT是Qt的宏,用于指明信号和槽,并将它们的参数转化为相应的字符串。假设我们给按钮添加信号,点击按钮关闭窗口,我们在setupUi()函数中可以看到如下语句:

QObject::connect(pushButton, SIGNAL(clicked()), QWDialogClass, SLOT(close()));

有关信号与槽,有以下注意事项:

  1. 当信号和槽函数带有参数时,connect()函数要写明参数类型,但是可以不屑=写参数名称;
  2. 一个信号可以连接多个槽。即一个信号可以触发多个响应。当一个信号与多个槽相关联的时候,槽函数按照建立时连接的顺序依次执行;
  3. 多个信号可以连接同一个槽。
  4. 一个信号可以连接另一个信号。当一个信号发射时,也会发射另一个信号,实现 某些特殊功能;
  5. 信号与槽的参数个数和类型需要一致,至少信号的参数不能少于槽的参数;
  6. 使用信号和槽,必须加入QObject宏;
  7. 当一个信号被发射,与其关联的槽函数立即被执行,只有槽函数执行完毕后才会继续执行发射信号处后面的代码。

在VS的QT Designer,功能并没有QT Creater齐全,我们要添加自定义的信号和槽还是需要我们自己去手写。并在QWDialog的构造函数中手工进行关联。

我们在QT Designer添加了系统的槽函数,但是发现我们的构造函数还是仅仅只有一条setupUi()语句。没有看到connect操作。我们去包含这个setupUi()函数的ui_xxxx.h文件也没有看到connect操作。但是有一条关键语句:

QMetaObject::connectSlotsByName(QWDialogClass);

这个函数将搜索QWDialog界面上所有的组件,将信号和槽关联起来。这就是用UI设计器可视化设计某个组件的响应信号槽函数,而不用手工将其关联起来的原因。都是在类界面的构造函数中调用setupUi()自动完成了关联。

代码化UI设计

界面设计的底层都是C++代码实现的,底层实现的功能比可视化设计更强大和灵活。
我们自己写一个界面,点击按钮关闭窗口。
在头文件中创建界面

#pragma once
//源码必须保存成带BOM的UTF-8格式,不然会有中文乱码
#pragma execution_character_set("utf-8") 

#include <QtWidgets/QDialog>
#include "ui_QWDlgManual.h"
#include<qpushbutton.h>

class QWDlgManual : public QDialog
{
    Q_OBJECT
public:
    QWDlgManual(QWidget *parent = Q_NULLPTR);

private:
    Ui::QWDlgManualClass ui;
    QPushButton *btn; //创建按钮
    void iniUI();   //UI创建与初始化
    void iniSignalSlots();  //初始化信号与槽的链接
};

界面的创建,以及信号与槽函数的关联都在构造里完成

QWDlgManual::QWDlgManual(QWidget *parent)
    : QDialog(parent)
{
    ui.setupUi(this);
    iniUI();  //创建界面与布局
    iniSignalSlots();  //信号与槽的关联
    setWindowTitle("Form created mannually");
}

在iniUI()函数中实现界面组件的创建,如果有布局也在这里创建。下方的iniSignalSlots()函数连接信号和槽:

void QWDlgManual::iniUI()
{
//    //创建按钮
    btn = new QPushButton("关闭",this);
    btn->setFixedSize(100, 100); 
}

void QWDlgManual::iniSignalSlots()
{
    connect(btn,SIGNAL(clicked()),this,SLOT(close()));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值