Qt学习(2)

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布局中,然后将该布局设置为中心布局,这样就可以在中心区域展示组件了,同时创建了自定义的槽,当触发相应事件的时候调用了自定义槽进行响应。同时也可以根据信号的实时状态来进行连接和断开。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode】挑战100天 Day14(热题+面试经典150题)

【LeetCode】挑战100天 Day14&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-162.1 题目2.2 题解 三、面试经典 150 题-163.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&…

nohup 实现远程运行不关机操作

nohup 实现远程运行不宕机操作 python nohup 实现远程运行不宕机操作 - python教程网 远程运行最怕断电&#xff0c;训练了几个小时的数据说没就没&#xff0c;或者停止运行。 用nohup 记录代码的输出&#xff0c;还可以不受断电的影响。 方法 1. 用nohup 运行一个python文…

HTML网站稳定性状态监控平台源码

这是一款网站稳定性状态监控平台源码&#xff0c;它基于UptimeRobot接口进行开发。当您的网站遇到故障时&#xff0c;该平台能够通过邮件或短信通知您。下面是对安装过程的详细说明&#xff1a; 安装步骤 将源码上传至您的主机或服务器&#xff0c;并进行解压操作。 在Uptim…

Redis高并发缓存架构

前言&#xff1a; 针对缓存我们并不陌生&#xff0c;而今天所讲的是使用redis作为缓存工具进行缓存数据。redis缓存是将数据保存在内存中的&#xff0c;而内存的珍贵性是不可否认的。所以在缓存之前&#xff0c;我们需要明确缓存的对象&#xff0c;是否有必要缓存&#xff0c;怎…

C++之模版初阶(简单使用模版)

前言 在学习C的模版之前&#xff0c;咱们先来说一说模版的概念&#xff0c;模版在我们的日常生活中非常常见&#xff0c;比如我们要做一个ppt&#xff0c;我们会去在WPS找个ppt的模版&#xff0c;我们只需要写入内容即可&#xff1b;比如我们的数学公式&#xff0c;给公式套值&…

DBS note5:Relational Algebra(关系代数)

目录 一、关系代数简介 二、Projection () 三、Selection () 四、Union () 五、Set Difference (-) 六、Intersection () 七、Cross Product () 八、Joins () 九、Rename () 十、Group By / Aggregation () 一、关系代数简介 关系代数中的所有运算符都接受一个关系并…

mac上Homebrew的安装与使用

打开终端&#xff1a;command空格 &#xff0c;搜索‘’终端 ’&#xff0c;打开终端 在终端中输入以下命令并按下回车键&#xff1a; /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"这个命令会自动下载并安装…

RocketMQ 消息中间件 知识点汇总

目录 RocketMQ1、什么是RocketMQ?常用术语:2、为什么需要消息队列3、什么是异步处理4、什么是服务解耦5、什么是流量控制6、消息队列两种模型队列模型:发布/订阅模型:总结:7、怎么保证消息不丢失8、如何处理消息被重复消费**出现消息重复的情况:****解决方法:**9、如何保…

github国内访问小解(windows)

git 下载安装 使用 github 前必须确保电脑上已经安装了 Git&#xff0c;可以从 Git 官方网站去下载。 官方的网站在国内访问会比较慢&#xff0c;这里可以选择国内镜像&#xff1a;https://registry.npmmirror.com/binary.html?pathgit-for-windows/ github 之旅 确认电脑已…

多功能PHP图床源码:Lsky Pro开源版v2.1 – 最新兰空图床

Lsky Pro是一款功能丰富的在线图片上传和管理工具&#xff0c;即兰空图床。它不仅可以作为个人云相册&#xff0c;还可以用作写作贴图库。 该程序的初始版本于2017年10月由ThinkPHP 5开发&#xff0c;经过多个版本的迭代&#xff0c;于2022年3月发布了全新的2.0版本。 Lsky Pro…

jQuery_02 引入jQuery,初试牛刀

引入jquery文件 我们在官网上点击dowmload那个 会发现进入了一个网页&#xff0c;里面全部是代码&#xff0c;你可能还在想为什么下载不了&#xff0c;其实jquery不跟vue一样&#xff0c;整个jquery就是一个js文件而已&#xff0c;所以直接ctrla 全选 ctrlc复制 &#xff0c;然…

PasteNow for mac剪贴板工具

PasteNow 是一款简单易用的剪贴板管理工具&#xff0c;可帮助用户快速存储和管理剪贴板上的文本和图片内容。用户可以使用 PasteNow 软件快速将文本内容保存到不同的笔记或页面中&#xff0c;也可以方便地将剪贴板上的图片保存到本地或分享给其他应用程序。 此外&#xff0c;P…

nodejs+vue+python+PHP+微信小程序-青云商场管理系统的设计与实现-安卓-计算机毕业设计

研究步骤、措施&#xff1a; &#xff08;1&#xff09;与指导老师确定系统主要功能&#xff1b; &#xff08;2&#xff09;做需求分析及功能模块划分&#xff1b; &#xff08;3&#xff09;指导老师通过后&#xff0c;设计出用例图&#xff0c;E-R图&#xff0c;功能模块图 …

Python开发运维:Django 4.2.7 使用Celery 5.3.5 完成异步和定时任务

目录 一、实验 1.Django使用Celery完成异步和定时任务 二、实验 1. 如何查看Django版本 一、实验 1.Django使用Celery完成异步和定时任务 (1)安装Django (2)新建Django项目 (3)初始框架 (4)urls.py引用视图views from django.contrib import admin from django.urls imp…

力扣每日一题-HTML实体解析器-2023.11.23

力扣每日一题&#xff1a;HTML实体解析器 开篇 这是今天的每日一题&#xff0c;中等难度&#xff0c;只要有耐心&#xff0c;应该是能够写出来的。下面给大家分享我的思路与代码。 题目链接: 1410.HTML实体解析器 题目描述 代码思路 1.创建一个哈希表&#xff0c;把要替换的…

基于SRGAN的人脸图像超分辨率

引言 SRGAN是第一个将GAN用在图像超分辨率上的模型。在这之前&#xff0c;超分辨率常用的损失是L1、L2这种像素损失&#xff0c;这使得模型倾向于学习到平均的结果&#xff0c;也就是给低分辨率图像增加“模糊的细节”。SRGAN引入GAN来解决这个问题。GAN可以生成“真实”的图像…

Windows IDEA Python开发环境安装+爬虫示例

文章目录 Python下载安装开发工具IDEA包管理安装pip基本用法从 requirements.txt 安装依赖 项目示例部署在 Linux 上安装Python在 Linux 上创建虚拟环境&#xff1a;安装依赖&#xff1a;运行你的爬虫 Python下载安装 Python 安装包下载地址&#xff1a;https://www.python.or…

nodejs微信小程序+python+PHP-书吧租阅管理系统的设计与实现-安卓-计算机毕业设计

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Navicat 技术指引 | GaussDB 数据查看器

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

前端vue导出PPT,使用pptxgen.js

前言 公司新需求需要导出ppt给业务用&#xff0c;查阅资料后发现也挺简单的&#xff0c;记录一下。 如有不懂的可以留言&#xff01;&#xff01;&#xff01; 1.安装包 npm install pptxgenjs --save2.引入包 在需要使用的文件中引入 import Pptxgenfrom "pptxgenjs&…