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然后调用ageChangesenderObj.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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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_OBJECTpublic: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);elsedisconnect(clickBtn, &QPushButton::clicked, this, &MainWindow::onClick);
}

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3之echarts渐变柱状图

vue3之echarts渐变柱状图 效果&#xff1a; 核心代码&#xff1a; <template><div class"abnormal"><div class"chart" ref"chartsRef"></div></div> </template><script setup> import * as echa…

树形 DP:树的直径

leetCode 104.二叉树的最大深度104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int maxDepth(TreeNode* root) {if(root nullptr) return 0;int lDepth maxDepth(root->left);int rDepth maxDepth(root->right);return max(l…

Java Web——XML

1. XML概述 XML是EXtensible Markup Language的缩写&#xff0c;翻译过来就是可扩展标记语言。XML是一种用于存储和传输数据的语言&#xff0c;它使用标签来标记数据&#xff0c;以便于计算机处理和我们人来阅读。 “可扩展”三个字表明XML可以根据需要进行扩展和定制。这意味…

LV.12 D19 ADC实验 学习笔记

一、ADC简介 1.1 ADC ADC(Analog to Digital Converter)即模数转换器&#xff0c;指一个能将模拟信号转化为数字信号的电子元件 1.2 ADC主要参数 分辨率 ADC的分辨率一般以输出二进制数的位数来表示&#xff0c;当最大输入电压一定时&#xff0c;位数越高&#xff0c…

【数据结构/C++】栈和队列_顺序栈

#include<iostream> using namespace std; #define MaxSize 10 // 1. 顺序栈 typedef int ElemType; struct Stack {ElemType data[MaxSize];int top; } SqStack; // 初始化栈 void init(Stack &s) {// 初始化栈顶指针s.top -1; } // 入栈 bool push(Stack &s, …

2023年c语言程序设计大赛

7-1 这是一道送分题 为了让更多的同学参与程序设计中来&#xff0c;这里给同学们一个送分题&#xff0c;让各位感受一下程序设计的魅力&#xff0c;并祝贺各位同学在本次比赛中取得好成绩。 注&#xff1a;各位同学只需将输入样例里的代码复制到右侧编译器&#xff0c;然后直…

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

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

@RequestMapping

目录 作用&#xff1a; 位置&#xff1a; 属性 1.value 2.method 3.params 4.header 作用&#xff1a; 该注解是一个用来处理请求地址映射的注解。 位置&#xff1a; 可用于映射一个请求或一个方法&#xff0c;可以用在类或方法上。 用于方法上&#xff0c;表示在类的…

微服务测试怎么做,看看这篇文章就懂了!

开发团队越来越多地选择微服务架构而不是单体结构&#xff0c;以提高应用程序的敏捷性、可扩展性和可维护性。随着决定切换到模块化软件架构——其中每个服务都是一个独立的单元&#xff0c;具有自己的逻辑和数据库&#xff0c;通过 API 与其他单元通信——需要新的测试策略和新…

C++:一文读懂智能指针

C11 引入了 3 个智能指针类型&#xff1a; 当使用智能指针时&#xff0c;我们首先需要包含 memory头文件&#xff0c;这个头文件包含了 C 标准库中智能指针的定义。 1.std::unique_ptr<T> &#xff1a;独占资源所有权的指针。 2.std::shared_ptr<T> &#xff1a;共…

「Verilog学习笔记」信号发生器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 方波的实现&#xff0c;较为简单&#xff0c;只需要设置一个计数器&#xff0c;使输出保持10个时钟为0&#xff0c;跳变为20&#xff0c;再保持10个时钟。依次循环。可以按…

RTMDet原理与代码解析

paper&#xff1a;RTMDet: An Empirical Study of Designing Real-Time Object Detectors official implementation&#xff1a;https://github.com/open-mmlab/mmdetection/tree/main/configs/rtmdet 本文的创新点 Backbone and Neck 在backbone的basic building block中采…