Qt 学习笔记_01

Qt 学习笔记_01

视频传送门

1 Qt项目默认创建的文件

此处的main函数是Application项目的Widgets Application,基类选择的是QWidgets

(1)main.cpp

#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[])
{
    //应用程序对象,有且只有一个
    QApplication a(argc, argv);
    
    //实例化窗口对象
    QWidget w;
    
    /***
    在B站教学视频演示中,新建了MyQWidget类,并让该类继承自QWidget,这样可以自定义QWidget的	   构造函数,使得只要构造该对象就能自动创建一系列的控件
    ***/

    //显示w窗口
    w.show();
    
    //让应用程序对象进入消息循环机制中,代母阻塞到当前行
    return a.exec();
}

(2)项目文件

#-------------------------------------------------
#
# Project created by QtCreator 2022-02-22T13:48:52
#
#-------------------------------------------------

#Qt包含的模块
QT       += core gui

#大于4以上的版本, 包含widgets模块(兼容)
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

#目标——生成exe文件的名称
TARGET = 01_Pro

#模板——应用程序模板
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

#源文件
SOURCES += \
        main.cpp \
        mywiget.cpp \
    mypushbutton.cpp

#头文件
HEADERS += \
        mywiget.h \
    mypushbutton.h

2 按钮与窗口控件常用API

(1)按钮

Qt中的坐标系 左上角为(0, 0),x以右为正方向,y以下为正方向

  • 创建 QPushButton * btn = new QPushButton

  • 设置父亲 setParent(this) 设置父亲可以让该对象显示在父亲中,并且再释放时通过对象树依次释放,当然也可以直接在构造方法中传入父亲创建对象

  • 设置文本 setText(“文字”)

  • 设置位置 move(宽,高)

(2)窗口

  • 重新指定窗口大小 resize

  • 设置窗口标题 setWindowTitle

  • 设置窗口固定大小 setFixedSize

myWidget.cpp 中的构造函数(myWidget 是继承自QWidget的自定义类)

myWidget::myWidget(QWidget *parent)
    : QWidget(parent)
{
    this->setWindowTitle("第一个图形窗口");
    this->resize(400, 200);
    //设置后不能调整窗口大小
    //this->setFixedSize(400, 600);
              
    QPushButton * btn1 = new QPushButton;
    btn1->setParent(this);
    btn1->setText("按钮1");

    QPushButton * btn2 = new QPushButton;
    btn2->setText("按钮2");
    btn2->move(300, 0);

}

效果如下

3 信号和槽

先介绍一下可以把信号和槽关联起来的connect函数(四个参数都是地址

connect(信号发送者, 发送的信号(函数地址), 信号的接受者, 处理的槽函数)

使用connect后,当特定事件发生时,发送者就会发送一个信号,接受者被连接的槽函数就会自动回调

(1)系统自带的信号和槽函数

//myWidget类的构造函数中
myPushButton * btn3 = new myPushButton(this);
btn3->setText("我自己的关闭按钮");
btn3->move(150, 75);
	
//这样连接后,当按下btn3按钮时,窗口就会关闭
connect(btn3, &QPushButton::clicked, this, &QWidget::close);

(2)自定义信号和槽

① 自定义信号

  • 写到 头文件的signals下

  • 返回值为void

  • 只需要声明,不需要实现

  • 可以有参数 ,可以重载

② 自定义槽函数

  • 写到 public slot下 或者public 或者全局函数

  • 返回值为 void

  • 既需要声明 ,也需要实现

  • 可以有参数 ,可以重载

  • emit 自定义信号 进行触发

案例:下课会触发 老师“饿了”信号, 学生响应信号,请客吃饭

//1. teacher.h中的signal(自定义信号只需要声明,不需要实现)
signals:
    void hungry();
    void hungry(QString food);
//2. student.h中的public slots
public slots:
    void treat();
    void treat(QString food);
//3. student.cpp中槽函数的实现
void Student::treat()
{
    qDebug() << "请老师吃饭!";
}
void Student::treat(QString food)
{
    //用qDebug打印调试信息时,QString类的内容会自动用" "括起来
    //qDebug() << "请老师吃饭, 老师要吃" << food;
    //去掉" "方法:先用toUtf8()转成QByteArray,再用data()转成char *
    qDebug() << "请老师吃饭, 老师要吃" << food.toUtf8().data();
}
//4. 定义一个下课函数,用来递交 老师"饿了"的信号
void Widget::classIsOver()
{
    emit tc->hungry("宫保鸡丁");
}
//5.1 (Widget.cpp的构造函数)如果没有重载的信号和槽,则可以用如下写法:
/*	
    //此处的tc和st分别为teacher.h和student.h类的指针,在Widget.h类中私有创建
    this->tc = new Teacher(this);
    this->st = new Student(this);
    QPushButton * btn = new QPushButton(this);
    btn->setText("下课");
    connect(btn, &QPushButton::clicked, tc, &Teacher::hungry);
    connect(tc, &Teacher::hungry, st, &Student::treat);
*/
	
//5.2 (Widget.cpp的构造函数) 有重载的信号或槽,需要用函数指针来指向特定参数的信号
    this->tc = new Teacher(this);
    this->st = new Student(this);
    //函数指针来指向 重载的有参函数地址
    void (Teacher:: *teacherSignal) (QString) = &Teacher::hungry;
    void (Student:: *studentSlot) (QString) = &Student::treat;
    connect(tc, teacherSignal, st, studentSlot);

    QPushButton * btn2 = new QPushButton(this);
    btn2->setText("下课(有参版)");
    connect(btn2, &QPushButton::clicked, this, &Widget::classIsOver);

//classIsOver函数实现
void Widget::classIsOver()
{
    //传参在这儿传的
    emit tc->hungry("鱼香肉丝");
}

(3)拓展

  • 信号可以连接信号
//点击按钮,老师发送"饿了"信号
connect(btn, &QPushButton::clicked, tc, &Teacher::hungry);
  • 一个信号可以连接多个槽函数

  • 多个信号可以连接同一个槽函数

  • 信号和槽函数的参数 必须类型一一对应

  • 信号的参数个数 可以多于槽函数的参数个数

  • 信号槽可以断开连接 disconnect

//断开连接
disconnect(tc,teacherSignal,st,studentSlot);
  • Qt4版本写法
//利用Qt4信号槽 连接无参版本
connect(zt,SIGNAL(hungry()) , st , SLOT(treat()));
/*
  Qt4版本 底层SIGNAL("hungry")  SLOT( "treat") 进行字符串比较
  Qt4版本优点:参数直观,缺点 :类型不做检测
  Qt5以上  支持 Qt4的版本写法
*/

(4) Lambda表达式

用Lambda表达式作为槽函数,能更简便的实现一些比较简单的槽函数

组成:

[capture](parameters) mutable ->return-type{
	statement
}
  • [] Capture 子句——内容为要访问Lambda表达式作用范围内所有可见的局部变量,为空则不访问, = 为值传递访问, & 为引用传递访问,也可以添加单个变量来单独访问该变量
//1. m按引用传递,其余按值传递
[=,&m](){
    //...
}
//2. a按值传递, 其余按引用传递
[&, a](){
    //...
}
//3. 函数体内可以使用lambda所在类中的所有成员变量
[this](){
	//...
}
//4. a值传递, b引用传递
[a, *b](){
	//...
}
  • ( ) 参数列表(可省略)
  • { } 实现体
//使用Lambda表达式来替代 classIsOver
connect(btn2, &QPushButton::clicked, this, [=](){
            emit tc->hungry("好吃的东西");
});
  • mutable 可修改标识符,添加后可以修改值传递的参数,但修改的只是备份,不能影响Lambda表达式外的变量值
//Lambda表达式外的m不会因为Lambda的操作而改变值
[m](){
	m = 1 + 2;
    qDebug() << m;
}
  • 返回值 -> 标识返回值类型,若返回值类型为 void 或 函数体内只有一条return,则可省略
int ret = []()->int{
    return 1000;
}
posted @   Liao_i  阅读(87)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示