Qt学习(2)

news2024/9/24 11:24:40

1.QObject

只有继承了QObject类的类,才具有信号槽的能力。所以,为了使用信号槽,必须继承QObject。凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。不管是不是使用信号槽,都应该添加这个宏。这个宏的展开将为我们的类提供信号槽机制、国际化机制以及 Qt 提供的不基于 C++ RTTI 的反射能力。因此,如果你觉得你的类不需要使用信号槽,就不添加这个宏,就是错误的。其它很多操作都会依赖于这个宏。

示例:

#include <QMainWindow>
#include <QString>
class A:public QObject{
public:
    A(QObject* parent=NULL):QObject(parent){
        qInfo()<<this<<"被构造";
        };
    ~A(){qInfo()<<this<<"被销毁";};
};
int main(int argc, char* argv[]){
    A objA;
    A* pA2=new A(&objA);  //将pA2挂在到objA下
    A* pA3 = new A(pA2);
    objA.dumpObjectTree();
}

这样子就会形成一个树结构。

QObject:: A
    QObject:: pA2
        QObject:: pA3

2.事件与信号

GUI应用程序都由事件驱动,事件主要由应用程序的用户生成,例如点击按钮,控件。或者由其他接触发生如:Internet连接,窗口管理器或计时器。当调用exec方法时,应用程序进入主循环。主循环将获取事件并发送到对象。

信号与槽 

信号和槽用于对象之间的通信。

//signal1调用到obj2的slot1
connect(Object1,signal1,Object2,slot1);

//signal1调用到obj3的slot1
connect(Object1,signal1,Object3,slot1);

 slot是普通的C++函数,当与之相连的信号发出时将调用。

连接信号和插槽的方式:

1.成员函数指针

connect(senderPtr,&QObject::destoryed,this,&MyObject::objectDestroyed);

2.仿函数或lambda表达式作为slot

connect(sender,&QObject::destoryed,this,[=](){this->m_object.remove(sender);}); 

学习示例:

头文件

#ifndef MYHEAD1_H_
#define MYHEAD1_H_
#include <QCoreApplication>
#include <QDebug>
class Sender : public QObject
{
    Q_OBJECT
public:
    explicit Sender(QObject* parent = nullptr);

private:
    int m_age = 10;

public:
    void incAge();
signals:
    // 信号函数无需定义,只需声明,并且不能有返回参数,但可以有输入参数
    void ageChanged(int value);
};

class Receiver : public QObject
{
    Q_OBJECT
public:
    explicit Receiver(QObject* parent = nullptr);
public slots:
    //槽函数为普通函数,需要定义,但也不能有返回值
    void ageChange(int age);
};
#endif  // MYHEAD1_H_

在main函数中调用:

#include "myhead1.h"
int main(int argc, char* argv[])
{
    Sender senderObj;
    senderObj.incAge();
    Receiver recriverObj;

    //传递信号,通过指针的方式传递
    QObject::connect(&senderObj,&Sender::ageChanged,&recriverObj,&Receiver::ageChange);
    
    //建立连接后,每次emit发送信号都会传递给reciver然后调用ageChange
    senderObj.incAge();
    senderObj.incAge();

    //断开连接         
    QObject::disconnect(&senderObj,&Sender::ageChanged,&recriverObj,&Receiver::ageChange);
    senderObj.incAge();
    return 0;
}

当建立连接后,每次emit发送信号后,都会执行相应的槽(slots),而段凯连接后则不会继续调用槽。

3.鼠标键盘响应

  在MainWindow构造函数中注册事件,在触发时让其发出信号调用对应处理槽.

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    // QWidget interface
protected:
    void keyPressEvent(QKeyEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
};
#endif // MAINWINDOW_H

实现文件

#include "mainwindow.h"

#include <QtWidgets>
MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
{
    // 开启鼠标跟踪
    setMouseTracking(true);
    // 创建一个按钮对象,入参为按钮显示名字和操作对象
    auto* quitBtn = new QPushButton("Quit", this);

    // 设置按钮位置和大小
    quitBtn->setGeometry(50, 25, 100, 50);

    // 创建连接,当按钮点击事件出发时,调用循环的退出函数
    connect(quitBtn, &QPushButton::clicked, qApp, &QApplication::quit);
}

MainWindow::~MainWindow()
{
}

void MainWindow::keyPressEvent(QKeyEvent* event)
{
    // 如果当前按键事件是esc键,则退出程序
    if (event->key() == Qt::Key_Escape)
        qApp->quit();
}

void MainWindow::mouseMoveEvent(QMouseEvent* event)
{
    // 获取当前鼠标X坐标
    int x = event->pos().x();
    // 获取y坐标
    int y = event->pos().y();
    QString text = "坐标:" + QString::number(x) + "," + QString::number(y);
    this->statusBar()->showMessage(text);
}

在其中,使用new QPushButton创建了一个按钮,并且在按钮中显示了文字,同时使用按钮中的方法来指定按钮的位置和大小(按照x,y轴来判断位置和创建按钮大小的).最后通过指针绑定按钮的点击事件,当按钮被按下时触发QPushButton::clicked,然后调用槽QApplication::quit用来退出程序。

其余的键盘检测按键和鼠标位置是通过重写QMainWindow类中的抽象函数来实现,当在窗口中检测到时会自动的进行调用.

4.控件与自定义槽

QWidget是用户界面的原子类。它接收鼠标、键盘和来自系统的其他事件,并在屏幕上将它们绘制出来。每个Widget都是矩形的,并按照Z-order(Z轴)进行排序。一个Widget夹在它的Parent和它前面的Widget之间。

没有嵌入parent widget中的Widget称为Window。通常情况下,Windows有一个Frame和标题栏(当然也可以通过window flags来取消这些项)。Qt中,QMainWindow和QDialog的多种多样的子类是最常见的Window类型.


 

这就是一个定义好的QMainWindow,其布局已经是默认规定好的,无法再去增加布局,但是可以创建布局然后替换对应的布局,并放入组件。

头文件:

#ifndef MAINWINDOW_H_
#define MAINWINDOW_H_
#include <QMainWindow>
class QPushButton;
class QLabel;
class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    QPushButton* clickBtn;
    QLabel* label;

    // QObject interface
protected:
    void timerEvent(QTimerEvent *event);

public slots:
    void onClick();
    void onCheck(int state);
};
#endif  // MAINWINDOW_H

实现文件:

#include "mainwindow.h"

#include <QtWidgets>
MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)

{
    // 创建一个布局
    QWidget* myWidget = new QWidget(this);

    // 替换到中心布局中
    setCentralWidget(myWidget);

    // 创建按钮
    clickBtn = new QPushButton("点击", myWidget);

    // 创建点击事件
    QCheckBox* cb = new QCheckBox("Connect", myWidget);

    // 设置点击事件默认状态
    cb->setCheckState(Qt::Checked);
    label = new QLabel(QTime::currentTime().toString(), myWidget);

    //横向的展示组件
    QHBoxLayout* hbox = new QHBoxLayout(myWidget);
    hbox->addWidget(clickBtn);
    hbox->addWidget(cb);
    hbox->addWidget(label);
    startTimer(1000);

    // 以指针的方式传入对象和函数
    connect(clickBtn, &QPushButton::clicked, this, &MainWindow::onClick);
    connect(cb, &QCheckBox::stateChanged, this, &MainWindow::onCheck);
}

MainWindow::~MainWindow()
{
}

void MainWindow::timerEvent(QTimerEvent* event)
{
    // 标识这个形参没有用到
    Q_UNUSED(event);
    label->setText(QTime::currentTime().toString());
}

void MainWindow::onClick()
{
    // 在底部标题栏展示信息
    statusBar()->showMessage("按钮被点击");
}

void MainWindow::onCheck(int state)
{
    statusBar()->showMessage("");

    // 根据QCheckBox状态来执行对应函数
    if (state == Qt::Checked)
        connect(clickBtn, &QPushButton::clicked, this, &MainWindow::onClick);
    else
        disconnect(clickBtn, &QPushButton::clicked, this, &MainWindow::onClick);
}

 从这个程序中,我们可以将组件装入到我们自己创建的widget布局中,然后将该布局设置为中心布局,这样就可以在中心区域展示组件了,同时创建了自定义的槽,当触发相应事件的时候调用了自定义槽进行响应。同时也可以根据信号的实时状态来进行连接和断开。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1248474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

dom api

dom的全称为Document Object Model,即文档对象模型.所谓文档就是html页面,对象就是js里的对象,通过这个模型把页面上的元素和js里的对象关联起来. 下面是关于dom api的一些常用方法 1.获取元素 使用querySelector()方法获取一个元素 使用querySelectorAll()方法获取所有元素 当…

MediaCodec详解

MediaCodec 是Android平台提供的一个API&#xff0c;用于对音频和视频数据进行编码&#xff08;转换为不同的格式&#xff09;和解码&#xff08;从一种格式转换回原始数据&#xff09;。它是Android 4.1&#xff08;API级别16&#xff09;及以上版本的一部分&#xff0c;允许开…

【C语言】函数(四):函数递归与迭代,二者有什么区别

目录 前言递归定义递归的两个必要条件接受一个整型值&#xff08;无符号&#xff09;&#xff0c;按照顺序打印它的每一位使用函数不允许创建临时变量&#xff0c;求字符串“abcd”的长度求n的阶乘求第n个斐波那契数 迭代总结递归与迭代的主要区别用法不同结构不同时间开销不同…

【Python】实现一个简单的区块链系统

本文章利用 Python 实现一个简单的功能较为完善的区块链系统&#xff08;包括区块链结构、账户、钱包、转账&#xff09;&#xff0c;采用的共识机制是 POW。 一、区块与区块链结构 Block.py import hashlib from datetime import datetimeclass Block:"""区…

智能头盔天眼摄像头、单兵执法记录仪等配合MESH自组网在应急指挥调度中的应用

智能头盔、天眼摄像头、头盔记录仪、头盔摄像头、单兵执法记录仪等配合MESH自组网在应急指挥调度中的应用。 20人背负单兵自组网&#xff08;带手咪&#xff09;到训练场&#xff0c;戴头盔&#xff0c;头盔上放头盔式摄像头&#xff0c;大功率自组网设置在制高点&#xff0c;…

改进YOLOv8 | YOLOv5系列:RFAConv续作,即插即用具有任意采样形状和任意数目参数的卷积核AKCOnv

RFAConv续作,构建具有任意采样形状的卷积AKConv 一、论文yolov5加入的方式论文 源代码 一、论文 基于卷积运算的神经网络在深度学习领域取得了显著的成果,但标准卷积运算存在两个固有缺陷:一方面,卷积运算被限制在一个局部窗口,不能从其他位置捕获信息,并且其采样形状是…

五种多目标优化算法(MOJS、NSGA3、MOGWO、NSWOA、MOPSO)求解微电网多目标优化调度(MATLAB代码)

一、多目标优化算法简介 &#xff08;1&#xff09;多目标水母搜索算法MOJS 多目标优化算法&#xff1a;多目标水母搜索算法MOJS&#xff08;提供MATLAB代码&#xff09;_水母算法-CSDN博客 &#xff08;2&#xff09;NSGA3 NSGA-III求解微电网多目标优化调度&#xff08;M…

c语言数字转圈

数字转圈 题干输入整数 N&#xff08;1≤N≤9&#xff09;&#xff0c;输出如下 N 阶方阵。 若输入5显示如下方阵&#xff1a; * 1** 2** 3** 4** 5* *16**17**18**19** 6* *15**24**25**20** 7* *14**23**22**21** 8* *13**12**11**10** 9*输入样例3输出样例* 1*…

腾讯云云服务器旗舰新品SA5重磅首发

近日&#xff0c;腾讯云云服务器CVM再升级&#xff0c;极具性价比的云服务器旗舰新机型SA5重磅发布&#xff0c;搭载第四代AMD EPYC处理器&#xff08;Bergamo&#xff09;&#xff0c; 相比云服务器SA3实例&#xff0c;整机性能最大提升120%以上。 温馨提醒&#xff1a;购买腾…

【Java 进阶篇】Jedis 操作 String:Redis中的基础数据类型

在Redis中&#xff0c;String是最基础的数据类型之一&#xff0c;而Jedis作为Java开发者与Redis交互的利器&#xff0c;提供了丰富的API来操作String。本文将深入介绍Jedis如何操作Redis中的String类型数据&#xff0c;通过生动的代码示例和详细的解释&#xff0c;让你轻松掌握…

基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码

基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于白鲸优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

【电子通识】什么是物料清单BOM(Bill of Material))

BOM (Bill of Materials)是我们常说的物料清单。BOM是制造业管理的重点之一&#xff0c;用于记载产品组成所需要的全部物料&#xff08;Items&#xff09;。物料需求的计算是从最终产品开始&#xff0c;层层往下推算出部件&#xff0c;组件&#xff0c;零件和原材料的需求量。这…

MindStudio学习一 整体介绍

一场景介绍 二 安装介绍 1.LINUX 采用无昇腾硬件采用linux 分部署 2.WINDOWS 3.linux下安装整体步骤 3.1安装依赖 3.2 安装步骤 1.gcc cmake 等依赖 2.python3.7.5 3.pip 安装依赖 4.安装JDK 5.安装 Ascend-cann-toolkit 6.解压安装Mindstudio 7.进入bin路径 ./…

Cortex-M与RISC-V区别

环境 Cortex-M以STM32H750为代表&#xff0c;RISC-V以芯来为代表 RTOS版本为RT-Thread 4.1.1 寄存器 RISC-V 常用汇编 RISC-V 关于STORE x4, 4(sp)这种寄存器前面带数字的写法&#xff0c;其意思为将x4的值存入sp4这个地址&#xff0c;即前面的数字表示偏移的意思 反之LOA…

基于广义正态分布算法优化概率神经网络PNN的分类预测 - 附代码

基于广义正态分布算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于广义正态分布算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于广义正态分布优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xf…

【LM358AD运放方波振荡器可控输出幅值】2022-2-25

缘由仿真如何缩小方波振荡电路方波幅值?-有问必答-CSDN问答

再生式收音机踩坑记

下载《A Simple Regen Radio for Beginners》这篇文章也有好几年了&#xff0c;一直没有动手&#xff0c;上周末抽空做了一个&#xff0c;结果相当令人沮丧&#xff0c;一个台也收不到&#xff0c;用示波器测量三极管振荡波形&#xff0c;只有在调节再生电位器R2过程中&#xf…

构造命题公式的真值表

构造命题公式的真值表 1&#xff1a;实验类型&#xff1a;验证性2&#xff1a;实验目的&#xff1a;3&#xff1a;逻辑联结词的定义方法4&#xff1a;命题公式的表示方法5&#xff1a;【实验内容】 1&#xff1a;实验类型&#xff1a;验证性 2&#xff1a;实验目的&#xff1a…

C语言——从终端(键盘)将 5 个整数输入到数组 a 中,然后将 a 逆序复制到数组 b 中,并输出 b 中 各元素的值。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int i;int a[5];int b[5];printf("输入5个整数&#xff1a;\n");for(i0;i<5;i){scanf("%d",&a[i]);}printf("数组b的元素值为&#xff1a;\n");for(i4;i>0;i--…

[原创](免改BIOS)使用Clover升级旧电脑-(高阶玩法)让固态硬盘内置Win11 PE启动系统

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XXQQ: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi…