首页 > 其他分享 >【QT5】<总览二> QT信号槽、对象树及样式表

【QT5】<总览二> QT信号槽、对象树及样式表

时间:2024-06-04 22:02:44浏览次数:14  
标签:总览 QT include 样式表 信号 MyWindow 树及 MainWindow

文章目录

前言

一、QT信号与槽

1. 信号槽连接模型

2. 信号槽介绍

3. 自定义信号槽

二、不使用UI文件编程

三、QT的对象树

四、添加资源文件

五、样式表的使用

六、QSS文件的使用


前言

承接【QT5】<总览一> QT环境搭建、快捷键及编程规范。若存在版权问题,请联系作者删除!


一、QT信号与槽

1. 信号槽连接模型

1.1 信号槽连接模型:

1.2 QT中信号槽的使用方式:

方式一:如下图所示,在ui设计器中的中下位置可以设置信号槽的四要素。下图实现了点击按钮就会关闭当前窗口的功能。

方式二:如下图所示,右击按钮,再点击“转到槽”,QT就会给MyWindow类自动在头文件中声明私有的void on_pushButton_clicked(); 同时也会转到源文件要求程序员实现点击的效果。

2. 信号槽介绍

2.1 概念:

  • 信号:在特定情况下被发射的事件。例如:PushButton最常见的信号就是鼠标单击时发射的click()信号。
  • 槽:对信号响应的函数。槽函数与普通的函数相比,不同在于:槽函数与指定的信号关联,当信号被发射时,该槽函数会被自动执行。

2.2 信号与槽的关联:

  • 方式:使用QObject::connect()函数。由于QT中所有类都是QObject的子类,因此可以省去QObject,其基本格式如下:
//sender 是发射信号的对象的名称
//signal() 是信号名称。信号可以看做是特殊的函数,需要带括号,有参数时还需要指明参数
//receiver 是接收信号的对象名称
//slot() 是槽函数的名称,需要带括号,有参数时还需要指明参数
//SIGNAL和SLOT是Qt的宏,用于指明信号和槽,并将它们的参数转换为相应的字符串
connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
  • 代码示例:
/* 1.mywindow.h头文件代码 */
#ifndef MYWINDOW_H
#define MYWINDOW_H
#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MyWindow; }
QT_END_NAMESPACE


class MyWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void pushButton_clicked();//自定义槽函数

private:
    Ui::MyWindow *ui;
};
#endif // MYWINDOW_H

/************************************************/

/* 2.mywindow.cpp代码  */
#include "mywindow.h"
#include "ui_mywindow.h"
#include <QDebug>

//MyWindow构造函数的具体实现
MyWindow::MyWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MyWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(pushButton_clicked()));
}

//MyWindow析构函数的具体实现
MyWindow::~MyWindow()
{
    delete ui;
}

//自定义槽函数的实现
void MyWindow::pushButton_clicked()
{
    static int i;
    qDebug() << i++ << " ";
}

2.3 信号与槽的解除连接:

  • disconnect(myObject, 0, 0, 0); 断开一切与 myObject 连接的信号或槽。
  • disconnect(myObject, SIGNAL(mySignal()), 0, 0); 断开所有连接到特定信号的东西。
  • disconnect(myObject, 0, myReceiver, 0); 与指定的接收者断开连接。

2.4 信号槽连接规则:

  • 一个信号可以连接多个槽(触发一个造成多个结果)
  • 多个信号可以连接同一个槽(多个触发源造成一个结果)
  • 一个信号可以连接另一个信号(连锁反应)

3. 自定义信号槽

3.1 自定义信号的语法:

//在类中使用signals关键字
//信号函数只声明不定义,并且返回值为void
signals:
    void sendMessage();//自定义信号函数

3.2 自定义槽的语法:

//使用slots自定义槽
//可以使用C++的三种权限符
//声明后必须给出定义
public slots:
    void goToClass();//自定义的槽函数

//槽函数定义
void Student::goToClass()
{
    qDebug() << "学生上课!" << endl;
}

3.3 案例:

背景:学校发出通知,学生收到后回到班级上课。根据此情景,创建School和Student类,并且在School类中自定义信号“发出通知”,在Student类中自定义槽“去班级”。为了简单演示,我们在MainWindow类中添加School和Studen类对象作为成员变量,在MainWindow的构造函数中创建对象,并构建“学校->通知->学生->上课”的信号槽连接,同时emit发射该信号,来观察实验现象。

①School.h:

#ifndef SCHOOL_H
#define SCHOOL_H

#include <QObject>

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

signals://自定义信号
    void sendMessage();//学校通知

};

#endif // SCHOOL_H

②Student.h:

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

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

signals:

public slots://自定义槽
    void goToClass();

};

#endif // STUDENT_H

③Student.cpp:

#include "student.h"
#include <QDebug>

Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::goToClass()
{
    qDebug() << "学生上课!" << endl;
}

④MainWindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "school.h"
#include "student.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
    School *school;
    Student *student;
};
#endif // MAINWINDOW_H

⑤MainWindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    school = new School(this);
    student = new Student(this);
    connect(school, SIGNAL(sendMessage()), student, SLOT(goToClass()));//信号与槽的连接
    emit school->sendMessage();//发射信号
}

MainWindow::~MainWindow()
{
    delete ui;
    delete school;
    delete student;
}


二、不使用UI文件编程

本章以按钮控件为例,说明仅编写代码来创建按钮。

步骤一:创建工程时取消勾选"Generate form":

步骤二:在mainwindow.h中声明按钮成员对象和头文件<QPushButton>:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPushButton>

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    QPushButton *pushButton;//按钮对象
};
#endif // MAINWINDOW_H

步骤三:在mainwindow.cpp中的构造函数里创建按钮对象,并设置相关属性:

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    pushButton = new QPushButton(this);         //实例化按钮
    pushButton->setText("我是按钮");             //设置按钮文本
    pushButton->setGeometry(50, 100, 100, 50);  //设置按钮位置
    this->resize(800, 480);                     //设置当前窗口大小
}

MainWindow::~MainWindow()
{
    delete pushButton;
}

三、QT的对象树

1. 为什么需要设置父对象?

答:因为需要将某些控件附着于父对象,以便能跟着父对象一起移动,方便控件的管理。

2. 如何设置父对象?

答:有构造函数传参和调用setparent()两种方式,如下所示:

//方式一:构造函数传入父对象地址
pushButton = new QPushButton(this);
//方式二:调用setParent函数
pushButton->setParent(this);

3. QT的对象树机制

答:父对象在调用析构函数前,会将附着于其上面所有的对象析构,再调用自己的析构函数。因此,可以不用显式地delete某些附着的对象,QT的对象树机制会自动将其销毁。


四、添加资源文件

有时需要外部的图片等资源,因此需要将资源文件添加进QT。

步骤一:将资源文件放置于当前工程目录下。

步骤二:添加"QT Resource File":

步骤三:添加资源路径的目录:

步骤四:添加外部图片:


五、样式表的使用

第四章已经加载了外部图片资源文件,本章改变样式表(stylesheet)将该图片呈现于窗口中。若不知道如何编写样式表的代码,可以去“帮助”中查找“stylesheet”查看“Qt Style Sheets Reference ”。

步骤一:在ui设计器中将QLable控件拖拽至窗口中:

步骤二:右击该控件,选中"改变样式表",添加图片:


六、QSS文件的使用

在第五章中,我们利用ui设计器来改变样式表从而加载外部图片。相应地,我们可以通过写代码的方式来改变样式表从而改变某些控件的外观。但是,当样式表书写过多时会影响我们代码的可读性。因此,可以通过qss文件来汇总这些样式表,而不需要在主程序中书写这些样式表。

原始效果:在Widget类的构造函数中写这些样式表。

我们将上述的样式表代码转移到qss文件中,减少主程序代码的复杂度。若不知道怎么写qss样式表,可以参考Qt QSS样式表总结

步骤一:新建qss文件:

步骤二:编辑qss文件:

步骤三:main()中加载qss文件:

运行结果:

/* 加载QSS文件 */
QFile file(":/style.qss");
if (file.exists()){
    file.open(QFile::ReadOnly);//只读方式打开
    QString styleSheet = QLatin1String(file.readAll());//字符串方式保存结果
    qApp->setStyleSheet(styleSheet);//设置全局样式
    file.close();//关闭文件
}

标签:总览,QT,include,样式表,信号,MyWindow,树及,MainWindow
From: https://blog.csdn.net/weixin_46249470/article/details/139422264

相关文章

  • QT添加样式表QSS/CSS文件后不起作用
    .qss和.css文件类似,CSS即层叠样式表(CascadingStyleSheets)可以修改组件的样式。在QT项目需要.css文件对组件进行样式设置,在qrc文件夹下添加文件之后,读取会失败,原因是添加文件需要点击添加现有文件,尽管所需文件在某个目录下,也不要选择添加目录。分别使用绝对路径、相对路径添......
  • 【编译器001-001】总览
    参考资料BuildingaCompiler国内搬运[中英字幕]C#构建编译器(BuildingaCompiler)代码地址:https://github.com/terrajobst/minsk具体思路这个作者使用的是dotnet,而我对dotnet不怎么感冒,所以我的方式是先使用dotnet跟着抄一遍,然后使用自己喜欢的语言写一......
  • C++U7-4-树及其应用(一)
    堆及其应用(一) 预先掌握 堆的定义堆:是一种特殊的树形数据结构,通常指的是二叉堆,可以被看作一棵完全二叉树。堆的特点是每个节点的值都大于等于(对于最大堆)或小于等于(对于最小堆)其子节点的值。堆的根节点包含最大值(最大堆)或最小值(最小堆)。用途:堆:主要用于实现优先队列,支持高......
  • C++U7-3-树及其应用
    树及其应用 树的表示方法       讲解哈夫曼树的基本概念            哈夫曼树的构造    哈夫曼编码的基本概念                作业讲解:链接:https://pan......
  • 最小生成树及扩展应用
    文章目录一、最小生成树1.1概念1.2定理一1.2.1内容1.2.2证明1.2.3推论1.3基于定理一推论的MST算法1.3.1Kruscal算法1.3.1.1算法原理1.3.1.2算法流程1.3.1.3代码实现1.3.2Prim算法1.3.2.1算法原理1.3.2.2算法流程1.3.2.3代码实现二、OJ练习2.1POJ125......
  • YuanDaiMa2048博客文章总览
    YuanDaiMa2048博客文章总览不定期更新学习中遇到的问题以及学习笔记…一、基础概念最新流行IT技术正则化概念及使用正则表达式基本概念正则表达式与正则化[日常使用]Win+R[日常使用]Shell常用命令dos和cmd二、科研工具[实验室服务器使用]使用VSCode、PyCharm、Mo......
  • 定义一棵松弛红黑树及其根结点颜色转换后的影响
    定义一棵松弛红黑树及其根结点颜色转换后的影响1.红黑树的性质2.松弛红黑树的定义3.根节点颜色变化的影响4.伪代码实现5.C语言代码实现6.结论在计算机科学中,红黑树是一种自平衡的二叉搜索树,它在许多数据结构和算法问题中都有着广泛的应用。红黑树通过一系列精心......
  • sytem verilog模型总览
    模板-V1模型功能systemverilog和verilog的区别:引入面向对象编程,类似C和C++的区别systemverilog的应用范围:硬件描述、系统仿真、系统验证systemverilog的使用方法:按照UVM或者其他验证方法学进行系统级仿真及验证模型框图systemverilog与verilog的主要区别属性veri......
  • CSS层叠样式表学习
    ---引入(Hello,大家好呀,欢迎大家和squirrel一起来学习CSS的相关知识,可以在评论区进行互动答疑哦,学无止境,加油!视频学习大家可以参考B站的黑马程序员pink老师的课程哦)一、CSS简介(目标:能够说出什么是CSS)CSS的主要使用场景就是美化网、布局页面的。 1.1HTML的局限性它只注......
  • CSS样式表 样式优先级 选择器以及选择器的权重优先级
     CSS组成    css由选择符和声明组成,声明又分为属性和属性值    属性必须放在花括号里面,属性与属性值必用冒号连接    每条声明用分号结束    当一个属性有多个属性值的时候,属性值与属性值部分先后顺序,用空格隔开    在书写样......