Qt --- 信号与槽

2023-05-16

信号与槽概述

信号与槽是 Qt 框架引以为豪的机制之一。所谓信号与槽,实际就是观察者模式(发布-订阅模式)。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

信号的本质

信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时候Qt对应的窗口类会发出某个信号,以此对用户的挑选做出反应。

因此根据上述的描述我们得到一个结论:信号的本质就是事件,比如:

  • 按钮单击、双击

  • 窗口刷新

  • 鼠标移动、鼠标按下、鼠标释放

  • 键盘输入

那么在Qt中信号是通过什么形式呈现给使用者的呢?

  • 我们对哪个窗口进行操作, 哪个窗口就可以捕捉到这些被触发的事件。

  • 对于使用者来说触发了一个事件我们就可以得到Qt框架给我们发出的某个特定信号。

  • 信号的呈现形式就是函数, 也就是说某个事件产生了, Qt框架就会调用某个对应的信号函数, 通知使用者。

在QT中信号的发出者是某个实例化的类对象,对象内部可以进行相关事件的检测。

槽的本质

槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private或 protected),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

举个简单的例子:

女朋友说:"我肚子饿了!",于是我带她去吃饭。

上边例子中相当于女朋友发出了一个信号, 我收到了信号并其将其处理掉了。

  • 女朋友 -> 发送信号的对象, 信号内容:我饿了

  • 我 ->槽:收信号的对象并且处理掉了这个信号, 处理动作: 带她去吃饭

在Qt中槽函数的所有者也是某个类的实例对象。

写信:发件人 信的内容 收件人 收到信做事情 - - ->通过邮局把他们联系到一起

信号和槽的关系

在Qt中信号和槽函数都是独立的个体,本身没有任何联系,但是由于某种特性需求我们可以将二者连接到一起,好比牛郎和织女想要相会必须要有喜鹊为他们搭桥一样。

信号与槽关联是用 QObject::connect() 函数实现的,其基本格式是:

[static] QMetaObject::Connection  QObject::connect(
    const QObject *sender, 						    		
    const char *signal, 								
    const QObject *receiver, 							
    const char *method, 								
    Qt::ConnectionType type = Qt::AutoConnection);	

静态成员 
发送者
信号的内容
接收者
方法
  • 参数:

    • sender:发出信号的对象

    • signal:信的内容,sender对象的信号,信号是一个函数

    • receiver:信号接收者

    • method:receiver对象的槽函数, 当检测到sender发出了signal信号, receiver对象调用method方法

connect函数相对于做了信号处理动作的注册,(建立关联)调用conenct连接信号与槽时,sender对象的信号并没有产生, 因此receiver对象的method也不会被调用,method槽函数本质是一个回调函数, 调用的时机是信号产生之后。 调用槽函数是Qt框架来执行的,connect中的sender和recever两个指针必须被实例化了, 否则conenct不会成功

标准信号与槽的使用

标准信号/槽

在Qt提供的很多类中都可以对用户触发的某些特定事件进行检测, 当事件被触发后就会产生对应的信号, 这些信号都是Qt类内部自带的, 因此称之为标准信号。

同样的,在Qt的很多类内部为我了提供了很多功能函数,并且这些函数也可以作为触发的信号的处理动作,有这类特性的函数在Qt中称之为标准槽函数。

系统自带的信号和槽通常如何查找,这个就需要利用帮助文档了,在帮助文档中比如我们上面的按钮的点击信号,在帮助文档中输入QPushButton,首先我们可以在Contents中寻找关键字 signals,但是我们发现并没有找到,这时候我们应该看当前类从父类继承下来了哪些信号,因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个

clicked:鼠标点击按钮一次,信号就会被触发

pressed:鼠标的左键 | 右键按下,信号就会被触发

released:按钮被释放,信号就会被触发

 widget.cpp

#include "widget.h"
#include<QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //构造函数
    //信号与槽
    //标准信号与槽:Qt类提供的,我们直接可以使用
    //connect(信号发送者,发送的内容|具体的信号,信号接收者,对应的处理动作)

    //先来一个按钮
    QPushButton *btn = new QPushButton;
    btn->setText("maye");
    //显示按钮
    btn->show();    
    //连接信号与槽
    connect(btn,&QPushButton::clicked,this,&Widget::close);
    //点击按钮按钮发送信号 类的成员函数指针:鼠标点击按钮时触发的信号
    //接收者:表示当前的Widget类用this指针标识 公有槽:关闭当前窗口
}
    //点击按钮后窗口关闭--->1.按钮发送clicked信号2.窗口对信号进行处理<->窗口关闭
Widget::~Widget()
{
}

使用

功能实现: 点击窗口上的按钮, 关闭窗口

  • 按钮: 信号发出者 -> QPushButton

  • 窗口: 信号的接收者和处理者 -> QWidget

// 单击按钮发出的信号
[signal] void QAbstractButton::clicked(bool checked = false)
// 关闭窗口的槽函数
[slot] bool QWidget::close();

// 单击按钮关闭窗口
connect(ui->closewindow, &QPushButton::clicked, this, &MainWindow::close);

自定义信号槽使用

Qt框架提供的信号槽在某些特定场景下是无法满足我们的项目需求的,因此我们还设计自己需要的的信号和槽,同样还是使用connect()对自定义的信号槽进行连接。

如果想要使用自定义的信号和槽,首先要编写新的类并且让其继承 Qt 的某些标准类,我们自己编写的类想要在Qt中使用使用信号槽机制,那么必须要满足的如下条件:

  • 这个类必须从 QObject 类或者是其子类进行派生

  • 在定义类的第一行头文件中加入 Q_OBJECT 宏

// 在头文件派生类的时候,首先像下面那样引入Q_OBJECT宏:
class MyMainWindow : public QWidget
{
    Q_OBJECT
public:
    ......
}

自定义信号与槽的简单了解

 signalAndslot.pro

QT += gui core widgets

CONFIG +=C++17

HEADERS += \
    mywindow.h

SOURCES += \
    main.cpp \
    mywindow.cpp

 mywindow.h

#ifndef MYWINDOW_H
#define MYWINDOW_H

#include<QPushButton>

class MyButton : public QPushButton  //1.必须间接或直接继承QObject QPushButton继承于QObject
{
    Q_OBJECT                         //2.必须包含Q_OBJECT宏
public:
    MyButton();
signals:                             //信号必须写在signals关键字下面,信号是函数的声明,不需要实现
    void testSignal();
public slots:                        //自定义槽函数:在访问权限词后面加slots代表槽函数
    void print();
};

#endif // MYWINDOW_H

 mywindow.cpp

#include "mywindow.h"
#include<QDebug>
MyButton::MyButton()
{
    //连接按钮的信号
    //信号不仅可以连接槽函数,还可以连接信号 1.自己被点击发出信号2.自己接收3.再发出自己信号4.信号被外部捕获|处理
    connect(this,&MyButton::clicked,this,&MyButton::testSignal);

    //connect(信号发送者,发送的内容|具体的信号,信号接收者,对应的处理动作)
    //连接自己的信号--->1.自己发出信号2.自己接收信号3.自己关闭窗口
    connect(this,&MyButton::testSignal,this,&MyButton::close);
    //点击一次按钮打印一次print
    connect(this,&MyButton::testSignal,this,&MyButton::print);

}

void MyButton::print()
{
    qDebug()<<"print";
}

 main.cpp

#include<QApplication>
#include"mywindow.h"
int main(int argc,char*argv[])
{
    QApplication a(argc,argv);

    MyButton w;      //创建按钮
    w.show();        //显示按钮 调用不了:没有继承任何类

    return a.exec();
}

自定义信号

  • 信号是类的成员函数

  • 返回值是 void 类型

  • 参数可以随意指定,信号也支持重载

  • 信号需要使用 signals 关键字进行声明, 使用方法类似于 public 等关键字

  • 信号函数只需要声明,不需要定义(没有函数体)

  • 在程序中发送自定义信号:发送信号的本质就是调用信号函数

emit mysignals();	//发送信号

 emit 是一个空宏,没有特殊含义,仅用来表示这个语句是发射一个信号,不写当然可以,但是不推荐。

// 举例: 信号重载
// Qt中的类想要使用信号槽机制必须要从QObject类派生(直接或间接派生都可以)
class MyButton : public QPushButton
{
    Q_OBJECT
signals:
    void testsignal();
    void testsignal(int a);
};
//qRegisterMetaType

信号参数的作用是数据传递, 谁调用信号函数谁就指定实参,实参最终会被传递给槽函数

自定义槽

槽函数就是信号的处理动作,自定义槽函数和自定义的普通函数写法是一样的。

特点

  • 返回值是 void 类型

  • 槽函数也支持重载

    • 槽函数参数个数, 需要看连接的信号的参数个数

    • 槽函数的参数是用来接收信号发送的数据的,信号的参数就是需要发送的数据

    • 举例

      • 信号函数:void testsig(int a,double b);

      • 槽函数:void testslot(int a,double b);

    • 总结

      • 槽函数的参数应该和对应的信号的参数个数, 类型一一对应

      • 信号的参数可以大于等于槽函数的参数个数,未被槽函数接受的数据会被忽略

        • 信号函数:void testsig(int a, double b);

        • 槽函数:void testslot(int a);

槽函数的类型

  • 成员函数

    • 普通成员函数

    • 静态成员函数

  • 全局函数

  • lambda表达式(匿名函数)

  1. 槽函数可以使用关键字进行声明: slots (Qt5中slots可以省略不写)

    • public slots:

    • private slots:

    • protected slots:

 场景举例

// 女朋友饿了, 我请她吃饭
// class GirlFriend
// class OneSelf
class GirlFriend:public QObject
{
    Q_OBJECT
public:
    GirlFriend(QObject*parent = nullptr):QObject(parent)
    {}
signals:
    void hungry();
public slots:
};

class OneSelf:public QObject
{
    Q_OBJECT
public:
    OneSelf(QObject*parent = nullptr):QObject(parent)
    {}
    void goEat()
    {
        qDebug()<<"goEat";
    }
    static void goEatFood()
    {
        qDebug()<<"goEatFood";
    }
signals:
public slots:
    void onHungry()
    {
        qDebug()<<"宝贝饿了呀,多喝热水哟~";
    }
};

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void onBtnClicked();
private:
    GirlFriend *girl;
    OneSelf* self;
};

 widget.cpp

#include "widget.h"
#include<QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    girl = new GirlFriend(this);
    self = new OneSelf(this);
    //连接槽函数
    connect(girl,&GirlFriend::hungry,self,&OneSelf::onHungry);
	//连接普通成员函数
    connect(girl,&GirlFriend::hungry,self,&OneSelf::goEat);
	//连接静态成员函数
    connect(girl,&GirlFriend::hungry,self,&OneSelf::goEatFood);
        

    QPushButton*btn = new QPushButton("按下就饿了",this);
    //通过widget间接发送girl的hungry信号    
    connect(btn,&QPushButton::clicked,this,&Widget::onBtnClicked);
     //连接信号,直接发送girl的hungry信号   
    //connect(btn,&QPushButton::clicked,girl,&GirlFriend::hungry);    

}

Widget::~Widget()
{
}

void Widget::onBtnClicked()
{
    emit girl->hungry();
}

信号槽拓展

信号槽使用拓展

  • 一个信号可以连接多个槽函数, 发送一个信号有多个处理动作

    • 需要写多个connect连接

    • 信号的接收者可以是一个对象, 也可以是多个对象

  • 一个槽函数可以连接多个信号, 多个不同的信号, 处理动作是相同的

    • 写多个connect就可以

  • 信号可以连接信号

    • 信号接收者可以不出来接收的信号, 继续发出新的信号 -> 传递了数据, 并没有进行处理

QPushButton*btn = new QPushButton("one",this);
QPushButton*btn2 = new QPushButton("two",this);
btn2->move(100,0);
//点击btn按钮,会让btn2按钮发出clicked信号
connect(btn,&QPushButton::clicked,btn2,&QPushButton::clicked);

connect(btn2,&QPushButton::clicked,this,&Widget::onClicked);
void Widget::onClicked()
{
    qDebug()<<"okok";
}
  • 信号槽是可以断开的
disconnect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);

信号槽的连接方式

Qt5的连接方式

// 语法:
QMetaObject::Connection QObject::connect(
    	const QObject *sender, PointerToMemberFunction signal, 
        const QObject *receiver, PointerToMemberFunction method, 
		Qt::ConnectionType type = Qt::AutoConnection);

// 信号和槽函数也就是第2,4个参数传递的是地址, 编译器在编译过程中会对数据的正确性进行检测
connect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);

Qt4的连接方式

这种旧的信号槽连接方式在Qt5中是支持的, 但是不推荐使用, 因为这种方式在进行信号槽连接的时候, 信号槽函数通过宏SIGNALSLOT转换为字符串类型。

因为信号槽函数的转换是通过宏来进行转换的,因此传递到宏函数内部的数据不会被进行检测, 如果使用者传错了数据,编译器也不会报错,但实际上信号槽的连接已经不对了,只有在程序运行起来之后才能发现问题,而且问题不容易被定位。

// Qt4的信号槽连接方式
[static] QMetaObject::Connection QObject::connect(
    const QObject *sender, const char *signal, 
    const QObject *receiver, const char *method, 
    Qt::ConnectionType type = Qt::AutoConnection);

connect(const QObject *sender,SIGNAL(信号函数名(参数1, 参数2, ...)),
        const QObject *receiver,SLOT(槽函数名(参数1, 参数2, ...)));

 应用举例

class Me : public QObject
{
    Q_OBJECT
// Qt4中的槽函数必须这样声明, qt5中的关键字 slots 可以被省略
public slots:
   	void eat();
    void eat(QString somthing);
signals:
	void hungury();
    void hungury(QString somthing);
};

基于上面写的信号与槽,我们来处理如下逻辑: 我饿了, 我要吃东西

  • 分析: 信号的发出者是我自己, 信号的接收者也是我自己

Me m;
// Qt4处理方式  注意不要把信号与槽的名字写错了,因为是转为字符串写错了不会报错,但是连接会失败
connect(&m, SIGNAL(eat()), &m, SLOT(hungury()));
connect(&m, SIGNAL(eat(QString)), &m, SLOT(hungury(QString)));

// Qt5处理方式
connect(&m, &Me::eat, &m, &Me::hungury);	// error:no matching member function for call to 'connect'
  • 为什么Qt4的方式没有错误,Qt5的方式却有问题了呢?

    • Qt4的方式在传信号和槽的时候用了宏进行强转,而且都带了参数,不会有二义性问题产生

    • Qt5中,信号和槽都有重载,此事connect函数根本就不知道你要使用的是重载中的哪一个,所以只能报错咯!

  • 如何解决Qt5中的信号和槽重载中的二义性问题呢?

    • 一、通过函数指针解决

//信号
void (Me::*funchungury)() = &Me::hungury;
void (Me::*funchungury_QString)(QString) = &Me::hungury;
//槽
void (Me::*funceat)() = &Me::eat;
void (Me::*funceat_QString)(QString) = &Me::eat;
//有参连接
connect(me,funchungury_QString,me,funceat_QString);
//无参连接
connect(me,funchungury,me,funceat);
  • 二、通过Qt提供的重载类(QOverload)解决
//有参连接
connect(this,QOverload<QString>::of(&MyButton::hungury),this,QOverload<QString>::of(&MyButton::eat));
//无参连接
connect(this,QOverload<>::of(&MyButton::hungury),this,QOverload<>::of(&MyButton::eat));
  • 总结
  • Qt4的信号槽连接方式因为使用了宏函数, 宏函数对用户传递的信号槽不会做错误检测, 容易出bug

  • Qt5的信号槽连接方式, 传递的是信号槽函数的地址, 编译器会做错误检测, 减少了bug的产生

  • 当信号槽函数被重载之后, Qt4的信号槽连接方式不受影响

  • 当信号槽函数被重载之后, Qt5中需要给被重载的信号或者槽定义函数指针

自定义信号与槽使用案例

 girlfriend.h

#ifndef GIRLFRIEND_H
#define GIRLFRIEND_H

#include<QObject>               //直接从Object类中继承
class GirlFriend  : public QObject
{
    Q_OBJECT
public:
    GirlFriend();
signals:
    void hungry();               //饿了信号
    void hungry(const QString);  //信号与槽的重载->可以存在多个名字相同的信号与槽函数 & 参数不同
};

#endif // GIRLFRIEND_H

 widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "girlfriend.h"
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots:
    void onBtnClicked();                //自定义槽函数--->响应什么控件的什么信号
    void onHungry();    
    void onHungry(const QString str);   //自定义槽函数重载
private:                                //一般情况下为私有属性
    GirlFriend girl;                    //栈区变量
};
#endif // WIDGET_H

 girlfriend.cpp

#include "girlfriend.h"

GirlFriend::GirlFriend()
{

}

 main.cpp

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

 widget.cpp

#include "widget.h"
#include<QPushButton>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QPushButton *btn = new QPushButton(this);       //创建专门用来触发饿了信号的按钮--->this:显示在窗口左上角的位置
    btn->setText("我饿了");
    connect(btn,&QPushButton::clicked,this,&Widget::onBtnClicked);
    //如果信号有重载,那么再连接的时候会产生二义性的问题--->不知道连接的是哪个信号|需要告诉它是有参版本还是无参版本的
//  connect(&girl,&GirlFriend::hungry,this,&Widget::onHungry);

    //1.类的成员函数指针--->类名限定 参数写在前面 
    // void GirlFriend::hungry()
    void (GirlFriend::*h)() = &GirlFriend::hungry;                  //定义了指向无参信号的指针
//  connect(&girl,h,this,&Widget::onHungry);

    void (GirlFriend::*hh)(const QString) = &GirlFriend::hungry;    //定义了指向有参信号的指针
//  connect(&girl,hh,this,&Widget::onHungry);
    //槽函数重载导致出现二义性--->Qt提供了一个函数专门用来处理重载问题
    //2.使用QOverload--->告诉它使用哪个hungry|onHungry
    connect(&girl,QOverload<>::of(&GirlFriend::hungry),
    this,QOverload<>::of(&Widget::onHungry));

    connect(&girl,QOverload<QString>::of(&GirlFriend::hungry),
    this,QOverload<QString>::of(&Widget::onHungry));
    //3.使用Qt4的方法,过时了,不推荐,为什么?
    //这两个宏实际上是把信号或槽函数转成了字符串,字符串不能一眼看出错误--->字符串不会进行检查
//  connect(&girl,SIGNAL(hungry()),this,SLOT(onHungry()));
//  connect(&girl,SIGNAL(hungry(const QString)),this,SLOT(onHungry(const QString)));

    connect(&girl,QOverload<QString>::of(&GirlFriend::hungry),
            this,QOverload<QString>::of(&Widget::onHungry));

    //信号与槽:
    /*1.一个信号可以和多个槽建立关联
     *2.信号也可以关联信号->转发
     *3.信号是函数的申明,而且返回值只能是void,信号的实现由Qt来实现
     *4.信号和槽都可以重载,但是在连接的时候,需要注意二义性问题(三种方法解决:函数指针、QOverload、Qt4方式)
     *5.5.1信号的参数一般和槽的参数一一对应
     *  5.2 槽的参数可以比信号的参数少(可以忽略信号的参数)
     *  5.3 槽的参数不能比信号的多(槽需要的参数信号没有,函数是需要传参的)
     *  5.4 槽是不能有默认参数的
     **/

    //lambda表达式做槽函数
    QPushButton *btn1 = new QPushButton(this);
    btn1->setText("我是按钮");
    btn1->move(200,0);

    //可以使用=,this捕获,但是最好不要使用&引用捕获
    connect(btn1,&QPushButton::pressed,this,[=]()
    {
        btn1->setText("你点了我");
        //this->move(100,100);
        //this->close();
    });
}

Widget::~Widget()
{

}

void Widget::onBtnClicked()
{
    qDebug()<<"宝,我饿了";
    //触发女朋友饿了信号,发送信号实际上就是调用信号函数
    emit girl.hungry();                //1.先打印 2.发送信号--->空宏:标识是用来发送信号
    emit girl.hungry("我要吃汉堡包");   //调用重载版本应该如何接收信号?
}

void Widget::onHungry()
{
    qDebug()<<"好的,带你去吃饭";
}

void Widget::onHungry(const QString str)
{
    qDebug()<<"好的,带你去吃汉堡";
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt --- 信号与槽 的相关文章

  • prometheus(普罗米修斯)

    prometheus 什么是普罗米修斯 xff1f Prometheus是一个开源系统监控和警报工具包 xff0c 最初是在 SoundCloud 上构建的 自2012年成立以来 xff0c 许多公司和组织都采用了Prometheus xf
  • 装机环境配置笔记

    装机过程中需要修改系统中的环境参数以及配置 xff01 xff01 xff01 http t csdn cn Ste4n xff08 记录在这里 xff09 运行环境配置文档 xff08 参考使用非必须 xff09 Notion The a
  • SDN系统方法 | 8. 网络虚拟化

    第8章 网络虚拟化 如第2章所述 xff0c 网络虚拟化和本书介绍的其他部分有所不同 xff0c 这是SDN第一个成功的商业用例 网络虚拟化可以在服务器上实现 xff0c 通常不需要物理网络中的交换机提供任何帮助 网络虚拟化可以实现为现有网
  • 算法设计与分析

    两个例子 调度问题与投资问题 例1 xff1a 调度问题 问题 有 n 项任务 xff0c 每项任务加工时间已知 从 0时刻开始陆续安排到一台机器上加工 每个任务的完成时间是从 0 时刻到任务加工截止的时间 求 总完成时间 xff08 所有
  • 偏航角、俯仰角、横滚角的理解

    最近研究IMU陀螺仪 xff0c 经过一早上的调试 xff0c 最后发现根本看不懂xyz三个角度的度数是怎么来的 xff0c 看了一些教程 xff0c 也觉得不够直观 xff0c 去了b站找了个视频 xff0c 发现讲解的还不错 xff0c
  • ubuntu20.04版本 安装ros1与px4、mavros、QGroundControl

    基于个人安装时的操作以及所浏览的链接 xff0c 仅供参考 文章目录 前言一 pandas是什么 xff1f 二 使用步骤 1 引入库2 读入数据总结 前言 使用ubuntu下载ros px4似乎是一件十分繁琐以及困难的事情 xff0c 但

随机推荐

  • ros中无人机基于话题<geographic_msgs/GeoPoseStamped.h>的指点飞行控制

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 前言一 话题认识二 完整代码总结 前言 本篇文章是作者在学习ros时根据自己的认识所写的代码 xff0c 主要是基于话题 lt
  • Jmeter性能测试(24)--dubbo接口测试

    一 Dubbo简介 dubbo是一个分布式服务框架 xff0c 致力于提供高性能和透明化的RPC远程服务调用方案 xff0c 以及SOA服务治理方案 其核心部分包含如下几点 xff1a 1 远程通讯 xff1a 提供对多种基于长连接的NIO
  • 自定义mavlink及收发测试(px4固件V1.11.0,QGC源码4.0)

    一 实现收 1 先定义uORB消息 a01 GPS msg uint64 timestamp time since system start microseconds uint64 lat Latitude uint64 lon Longi
  • 自定义mavlink及收发测试2(px4固件V1.11.0,QGC源码V4.0)

    一 1 下载安装一个mavlink文件或者在原文件上修改 安装步骤 xff08 包含mavlink generator xff09 可参照文章 PX4自定义Mavlink消息 xff08 一 xff09 px4发送 Sense97的博客 C
  • Ubuntu20.04 | 更新软件源 sudo apt-get update 出现错误

    之前使用了清华的官方源 清华大学开源软件镜像站 Tsinghua Open Source Mirror 错误提示 xff1a 忽略 1 https mirrors tuna tsinghua edu cn ubuntu focal InRe
  • PCB封装库的制作

    以下几个元件制作为例 xff1a 元件SMA封装 步骤 xff1a 1 创建PCB库文件 xff1a 单击 File 菜单 xff0c 选择 New 选项中的 Library 选项 xff0c 再选择 PCB Library xff0c 进
  • PCB板自动布线

    自动布线 步骤 xff1a 1 整体删除同层的走线 xff1a 打开PCB文件 xff0c 在层的选项卡中选择顶层 Top Layer xff0c 在 Edit 菜单下选择 Select 选项 xff0c 选择 All on Layer 选
  • 独立按键实验

    按键简介 按键是一种电子开关 xff0c 使用时 xff0c 按下按钮 xff0c 则开关接通 xff0c 松开手时 开关断开 开发板上使用的按键及内部简易图如下图所示 xff1a 按键管脚两端距离长的表示默认是导通状态 xff08 1 2
  • IO 扩展(串转并)-74HC595-16*16LED点阵实验

    51 单片机的IO 口非常有限 xff0c 有时候若想要连接更多外围设备 xff0c 需要通过 IO 扩展来实现 本文介绍一种 IO 口扩展方式 串转并 xff0c 使用的芯片是 74HC595 若有4个 74HC595 芯片 xff0c
  • LED 点阵实验~点亮一个点、数字、汉字、图

    LED 点阵简介 LED 点阵是由发光二极管排列组成的显示器件 xff0c 如下所示为8 8LED 点阵 xff1a 以 16 16LED 点阵为例 xff0c 其内部结构图如下所示 xff1a 16 16 点阵共由 256 个发光二极管组
  • 定时器中断

    定时器简介 介绍定时器之前 xff0c 先说明几个CPU 时序的有关知识 振荡周期 xff1a 为单片机提供定时信号的振荡源的周期状态周期 xff1a 1 个状态周期 61 2 个振荡周期机器周期 xff1a 1 个机器周期 61 6 个状
  • 红外遥控实验

    红外线简介 人眼所能看到的可见光 xff0c 按波长从长到短排列 xff0c 依次为红 xff08 660nm xff09 橙 xff08 610nm xff09 黄 xff08 585nm xff09 绿 xff08 555nm xff0
  • Jmeter性能测试(25)--linux环境运行jmeter并生成报告

    jmeter是一个java开发的利用多线程原理来模拟并发进行性能测试的工具 xff0c 一般来说 xff0c GUI模式只用于创建脚本以及用来debug xff0c 执行测试时建议使用非GUI模式运行 这篇博客 xff0c 介绍下在linu
  • 题目:输入三个整数x,y,z,把这三个数由小到大输出

    程序分析 xff1a 方式一 xff1a 先将两个数比较 xff0c 再将较大值与第三个数比较 xff0c 得到最大值 然后比较剩余的两个值 最后 xff0c 将数值以X lt Y lt Z的顺序输出 方式二 xff1a 将三个数分别两两进
  • 对话框QDialog

    对话框是 GUI 程序中不可或缺的组成部分 很多不能或者不适合放入主窗口的功能组件都必须放在对话框中设置 对话框通常会是一个顶层窗口 xff0c 出现在程序最上层 xff0c 用于实现短期任务或者简洁的用户交互 Qt 中使用QDialog类
  • 布局管理器~登录界面的搭建实例

    所谓的图形用户界面 xff08 GUI xff09 xff0c 本质上就是一堆组件的叠加 创建一个窗口 xff0c 把按钮放上面 xff0c 把图标放上面 xff0c 这样就成了一个界面 因此 xff0c 组件位置的放置尤其重要 xff0c
  • 常用控件及自定义控件

    QLabel QLabel可以用来显示文本 xff0c 图片和动画等 显示文本 xff08 普通文本 HTML xff09 通过QLabel类的setText函数设置显示的内容 void setText const QString amp
  • Dev-c++ 5.11版本调试方法(七小时折磨调试成功,超详细版)

    一 出现的问题是 1 设置断点之后点调试不出现蓝行 2 点了调试之后出现黑框 然后又闪退 3 添加查看之后也看不了变量的值 等等各种问题 xff08 查找 一个个试验 xff0c 还有整理 xff0c 花了起码六七小时 xff0c 几乎一天
  • Pycharm调试Debug篇(详细)

    pycharm中的debug模式 首先 xff0c 还是用示例说话 xff0c 我们书写一段简短的代码 xff0c 来帮我们完成今天要讲的内容 def sum demo x y for in range 2 x 43 61 1 y 43 6
  • Qt --- 信号与槽

    信号与槽概述 信号与槽是 Qt 框架引以为豪的机制之一 所谓信号与槽 xff0c 实际就是观察者模式 发布 订阅模式 当某个事件发生之后 xff0c 比如 xff0c 按钮检测到自己被点击了一下 xff0c 它就会发出一个信号 xff08