Qt学习(一、Qt简介,信号和槽)

一、 安装

。。。。。。

二、 创建第一个Qt程序

创建

  1. 新建,选择Qt Widgets Application

  2. 选择位置,选择构建套件

  3. 选择类的信息,其中 基类 有三种选择。

    • QMainwindow (多一个菜单栏)
    • QWidget (空窗口)
    • QDialog (对话框)

    其他两个是QWidget的子类。

    有两种方式创建图形界面:代码/拖拽

  4. 点击完成,会生成几个文件。源文件和头文件。还有一个 ***.pro 文件。

    其中:***.pro为工程文件。

分析代码

main.cpp:程序的入口

#include "widget.h"
// 包含一个应用程序类的头文件
#include <QApplication>

// argc 为命令行变量的数量; argv 为命令行变量的数组
int main(int argc, char *argv[])
{
    // a 为应用程序对象,在Qt中,应用程序对象有且仅有一个
    QApplication a(argc, argv);
    // 定义一个窗口对象 w ,Widget 的父类为 QWidget
    Widget w;
    // 窗口对象默认不会显示,必须要调用show方法显示窗口
    w.show();

    // 让应用程序对象进入消息循环
    return a.exec();
}

.pro 文件解释:

QT       += core gui		// Qt包含的模块
img
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets		// 大于4版本以上,包含Widget模块
TARGET = MyFirstQtApp		// 目标 生成的.exe程序的名称
TEMPLATE = app				// 模板 应用程序得模板
SOURCES += \
        main.cpp \
        widget.cpp			// 源文件

HEADERS += \
        widget.h			// 头文件

头文件:

// 防止头文件重复包含 if not define
#ifndef WIDGET_H
#define WIDGET_H

// 包含头文件 QWidget 窗口类
#include <QWidget>

// Widget 公有继承自 QWidget
class Widget : public QWidget
{
    // Q_OBJECT 宏, 允许类中使用信号量和槽的机制
    Q_OBJECT

public:
    // 构造函数 和 析构函数
    Widget(QWidget *parent = 0);
    ~Widget();
};

#endif // WIDGET_H

源文件:

#include "widget.h"

// 构造函数的实现,初始化列表
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
}

Widget::~Widget()
{

}

三、 创建按钮

#include "widget.h"
#include <QPushButton>

// 构造函数的实现,初始化列表
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // 创建一个按钮
    QPushButton* btn = new QPushButton;
    // btn->show(); show以顶层方式弹出窗口控件
    
    // 让btn对象依赖在Widget窗口中
    btn->setParent(this);
    btn->setText("第一个按钮");

    // 创建第二个按钮,按照控件的大小创建窗口
    QPushButton* btn2 = new QPushButton("第二个按钮",this);
    // 直接创建会将第一个按钮覆盖掉
    // 可以移动btn2按钮
    btn2->move(100,100);
    // 重新设置按钮大小
    btn2->resize(200,200);
    // 重置窗口大小
    resize(600,400);
    // 设置固定的窗口大小
    setFixedSize(600,400);
    
    // 设置窗口标题
    setWindowTitle("第一个窗口");
}

Widget::~Widget()
{

}

Qt中的对象树

Qt中的对象树就是Qt中对象间的父子关系,每一个对象都有它所有子对象的指针,都有一个指向其父对象的指针。当创建对象在堆区时,如果指定的父亲是QObject派生下来的类或者是QObject的子类派生下来的类,当父对象被析构时子对象也会被析构。在一定程度上简化了内存回收机制。

Qt中的窗口坐标系

窗口左上角为原点(0,0)。横方向为X轴,竖方向为Y轴。

四、 信号和槽

信号和槽是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。

在 Qt 中,用户和控件的每次交互过程称为一个事件,比如“用户点击按钮”是一个事件,“用户关闭窗口”也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出“按钮被点击”的信号,用户关闭窗口会发出“窗口被关闭”的信号。

Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到“按钮被点击”的信号后,会做出“关闭自己”的响应动作;再比如输入框自己接收到“输入框被点击”的信号后,会做出“显示闪烁的光标,等待用户输入数据”的响应动作。在 Qt 中,对信号做出的响应动作就称为槽。

信号和槽机制底层是通过函数间的相互调用实现的。每个信号都可以用函数来表示,称为信号函数;每个槽也可以用函数表示,称为槽函数。

举例

点击第二个按钮按钮关闭窗口。

// connect(信号发送者,发送的信号[函数地址],信号接受者,处理的槽函数[函数地址]);
connect(btn2,&QPushButton::clicked,this,&Widget::close);

connect()QObject 类中的一个静态成员函数,专门用来关联指定的信号函数和槽函数。

自定义的信号和槽举例

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);
    void OverClass();
signals:
    // 自定义信号 写在singal下
    // 返回值是void 只需要声明 不需要实现
    // 可以有参数 可以发生重载
    void hungry();

public slots:
};

#endif // TEACHER_H
#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);

signals:

public slots:
    // 早期Qt版本,必须要写到public slots,高级版本可以写到public或者全局下
    // 返回值 void 需要声明 需要实现
    // 可以有参数 可以发生重载
    void treat();
};

#endif // STUDENT_H
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "teacher.h"
#include "student.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
    // 分别定义两个对象
    Teacher* t ;
    Student* s ;
};

#endif // WIDGET_H
#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{

}

void Teacher::OverClass()
{
    emit this->hungry();
}
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::treat()
{
    // 在控制台输出 需要包含头文件
    qDebug() << "请老师吃饭" ;
}
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // 创建两个对象
    t = new Teacher(this);
    s = new Student(this);
    // 注意:下面两步是有顺序的
    // 老师饿了 学生请客的 连接
    connect(t,&Teacher::hungry,s,&Student::treat);
    // 调用下课函数
    t->OverClass();
}

Widget::~Widget()
{

}
#include "widget.h"
#include <QApplication>

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

    return a.exec();
}

信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:

  • 信号函数用 signals 关键字修饰,槽函数用 public slotsprotected slots 或者 private slots 修饰。signalsslots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;
  • 信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。

自定义的信号和槽发生重载

需要用到函数指针:

函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。

// 声明格式:类型说明符 (*函数名) (参数)
int (*fun)(int x,int y);
// 函数指针是需要把一个函数的地址赋值给它,有两种写法
fun = &Function;
fun = Function;
// 取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址
// 调用函数指针的方式也有两种:
x = (*fun)();
x = fun();
// 函数指针 指向 函数地址
void (Teacher::*teacherSignal)(QString) = &Teacher::hungry;
void (Student::*studentSlot)(QString) = &Student::treat;

connect(t,teacherSignal,s,studentSlot);
t->OverClass();
void Student::treat(QString FoodName)
{
    // 去掉Qstring中的引号
    // 将QString先转为QByteArray,再转为 char*
    qDebug() << "请老师吃:" << FoodName.toUtf8().data();
}

信号连接信号

// 点击按钮 触发下课
QPushButton* btn = new QPushButton("下课",this);
this->resize(600,400);
connect(btn,&QPushButton::clicked,t,&Teacher::OverClass);

断开信号

可以利用disconnect断开信号连接

// 信号断开操作 参数与connect一样
disconnect(btn,&QPushButton::clicked,t,&Teacher::OverClass);

Lambda表达式

匿名函数对象。。。先空着

其他

  • 一个信号可以连接多个槽函数
  • 多个信号可以连接同一个槽函数
  • 信号和槽函数的参数类型必须一一对应
posted @   ProEmon  阅读(787)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示