QT:基础与信号槽

1.基础理解

1.1初始代码

源文件

cpp 复制代码
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

QApplication是QT程序中必备的对象,他需要获取main中的命令行参数和命令行参数个数

w是定义好的类的对象,使用show()接口可以让控件显示出来

头文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

1.QWidget是我们选择的父类,其为QT的sdk中内置的类,使用的时候直接包含和类同名的头文件即可

使用时,先直接使用,如果发现没有包含头文件再包含即可,因为头文件包含是可以间接包含的

2.Q_OBJECT 是一个宏,展开之后会生成一大堆代码,当我们某个类想使用信号和槽的时候就要引入该宏

**3.parent指针:**QT中引入了对象树的概念,创建QT的对象需要把对象挂到对象树上,往树上挂的时候需要指定父节点

ui文件

点开之后会进入图形化设计界面,他的文件内容本质上是一个xml格式的代码

pro文件

qmake和.pro文件的作用和Makefile的作用是类似的

1.2实现简单helloworld窗口

Label标签

ui拖拽实现

先点击.ui文件,进入图形化设计窗口,然后将label拖入窗口,修改label的名字为helloworld

代码实现

如果使用的是QWIDGET类,就写到widget的构造函数中

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //创建基于父对象widget w的子类对象label
    QLabel* label = new QLabel(this);
    //设置标签文本
     label->setText("hello");
}

疑问:如果我们将对象申请在栈上,启动程序会发生什么?

会让窗口无法显示label,因为label对象在构造函数的栈空间释放的时候跟着释放了

所以我们选择使用堆空间给label

疑问:这里动态申请的对象空间为什么不用释放资源?

不是不释放,而是不需要手动释放资源,一般会在窗口消失的时候根据对象树的结构对所有对象资源进行释放

补充:QT中的库

QString,QVector等,他们和c++后来完善的std::string,std::vector类似,不过在QT开发中还是使用QT库中的会更好


Line Edit编辑框与Text Edit编辑框

代码实现:用编码创建编辑框

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include<QLineEdit>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QLineEdit* line = new QLineEdit(this);
    line->setText("hello world");
}

Widget::~Widget()
{
    delete ui;
}

Button按钮

代码实现:使用ui拖拽创建button

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->pushButton,&QPushButton::clicked,this,&Widget::handleClick);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::handleClick()
{
    if(ui->pushButton->text() == QString("hello"))
    {
        ui->pushButton->setText("hi");
    }
    else
    {
        ui->pushButton->setText("hello");
    }
}

核心是使用了connect接口,该接口可以让按钮关联信号槽,类似监听

connect格式解释:

参数1:表示谁发送信号

参数2:表示表示如何触发信号

参数3:表示负责处理信号的对象

参数4:表示接受到信号之后的处理函数地址(由负责处理信号的对象提供的成员函数)

注意:

pushButton是objectName的值,如果修改了这里objectName的值,那么使用的时候也要修改名字


疑问:我们应该怎么选择构造界面的形式?使用图形化方式还是纯代码方式?

两者皆要,因为图形化适用于界面固定,纯代码方式适合界面动态变化跳转的情况

疑问:qt中的命名规范是什么?
小驼峰命名:给变量和函数

eg:studentCount

大驼峰命名:给类

eg:QApplication

1.3实现自定义的标签对象

我们除了直接使用库的QLabel外,还可以根据实际需求创建自定义的label类

实际上就是通过继承库的QLabel来拓展更多自定义功能

头文件

cpp 复制代码
#ifndef MYLABEL_H
#define MYLABEL_H
#include<Qlabel>
#include<QWidget>
class MyLabel : public QLabel
{
public:
    MyLabel(QWidget* parent);
    ~MyLabel();
};

#endif // MYLABEL_H

源文件

cpp 复制代码
#include "mylabel.h"

MyLabel::MyLabel(QWidget* parent) 
    :  QLabel(parent)
{
    
}

MyLabel::~MyLabel()
{
    
}

注意:

**1.**构造函数一定要有parent,这是对象树生效的前提

**2.乱码处理:**由于windows默认的字符集不是utf8,所以我们直接使用cout输出中文字符会出现乱码,qt库QDebug可以帮我们自动解决转码问题

使用方式:

cpp 复制代码
qDubug() << "中文字符";

快捷键:

1.头/源文件切换:F4

2.利用声明生成定义代码:Alt+Enter

1.4QT中的坐标系

qt使用的坐标系是左手坐标系,y轴往下是正方向,x轴往右是正方向

**对于没有父元素的控件:**原点为整个屏幕的左上角

**对于有父元素的控件:**原点为父元素的左上角

我们可以使用两种方式来控制控件的位置

1.图形化界面直接移动:快速定位,但是不精确

2.编码控制:更精细化(使用move(水平移动像素值,垂直移动像素值))

2.信号和槽

信号和槽的三个重要要素

**1.信号源:**信号由谁发出

**2.信号类型:**是那种类型的信号

**3.信号处理(槽):**信号处理的函数,也叫槽,本质上是回调函数

2.1connect函数与disconnect函数

建立信号和槽的连接:connect

connect是QObject提供的静态成员函数,而QObject是qt中所有类的祖宗类,所以所有的控件实例化对象都可以使用connect进行信号处理

结构大致如下:

注意:

1.connect的第一和第二个参数必须是同一个类的,简单来说,我们的信号源是QPushButton,那么信号触发的类型也要是QPushButton的,不能是其他控件的

2.图标中,像梳子的表示槽函数,像wifi信号的表示信号函数

eg:

click表示进行点击操作,clicked表示触发了点击信号(已经被点击)


断开信号和槽的连接:disconnect

使用方法和connect类似

cpp 复制代码
disconnect(this,&Widget::mySignal,this,&Widget::handleMySignal);

2.2自定义信号与槽

使用前提:在对应类中写下Q_OBJECT宏


自定义槽:

方法一:使用connect(代码创建控件)

我们只要在负责处理信号的类中声明一个槽函数,然后再.cpp文件中对槽函数进行实现即可

最后connect就可以使用我们在类中声明的自定义槽函数

方法二:通过槽函数名绑定(图形化创建控件)

我们可以直接在图形化界面绑定槽函数,然后qtcreator就会自动生成自定义槽函数的声明的空定义

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    
}

然后底层就调用了根据槽函数名绑定控件的方法,从而不用使用connect

补充:

如果槽函数比较简单且为单次使用,我们可以使用lambda函数来当成槽函数使用


自定义信号:

构建自定义信号,只需要写出声明即可,qt会自动生成信号函数的定义,返回值必须是void

但是和qt内置的信号不同,他需要我们在特定情况下手动发送信号

在widget中直接声明信号函数即可,不用自己写定义

在connect了自定义信号和对应槽函数后,我们还需要在点击按钮触发clicked信号之后进入的槽函数on_pushButton_clicked中发送自定义信号,从而才能进入自定义信号处理槽函数中

2.3信号与槽的参数

信号和槽都可以携带参数,主要目的是为了复用一套信号槽,实现不同的效果(类似多态)

信号的参数个数大于等于槽的参数个数

假设槽的参数个数为n,信号的前n个参数槽的参数必须完全一致,前n个参数会从信号传递给槽,剩下的都被槽直接丢弃

相关推荐
小温冲冲2 小时前
Qt WindowContainer 完整实战示例:QWidget 嵌入 QML
开发语言·数据库·qt
熙街丶一人2 小时前
css 图片未加载时默认高度,加载后随图片高度
前端·javascript·css
xiaoliuliu123452 小时前
Android Studio 2025 安装教程:详细步骤+自定义安装路径+SDK配置(附桌面快捷方式创建)
java·前端·数据库
紫_龙2 小时前
最新版vue3+TypeScript开发入门到实战教程之Pinia详解
前端·javascript·typescript
533_2 小时前
[echarts] 使用scss变量
前端·echarts·scss
小李云雾2 小时前
零基础-从ESS6基础到前后端联通实战
前端·python·okhttp·中间件·eclipse·html·fastapi
SAP小崔说事儿2 小时前
SAP B1 批量应用用户界面配置模板
java·前端·ui·sap·b1·无锡sap
Amos_Web2 小时前
Rspack 源码解析 (1) —— 架构总览:从 Node.js 到 Rust 的跨界之旅
前端·rust·node.js
qq_406176142 小时前
React 组件传参 & 路由跳转传参
前端·javascript·react.js