QT基础【7-跨进程发送信号】

在这里插入图片描述

在这里插入图片描述

🌈个人主页:godspeed_lucip
🔥 系列专栏:QT从基础到进阶



1 跨进程发送信号

项目代码下载:提取码:ikun

其实与跨界面发送信号是一致的,只不过是发送信号的一方变成了进程

1.1 添加子进程类

  1. 选择C++ class

image-20240130211324133

  1. 选择其父类为QThread(也可以自行在代码中继承QThread)

image-20240130211448950

  1. 点击完成即可。

image-20240130211538102

非基础类型数据的注册

此处我们要使用一个score结构体,要是没有注册,则会报错:

QObject::connect: Cannot queue arguments of type 'score'
(Make sure 'score' is registered using qRegisterMetaType().)

注册如下:

将score结构体注册,用score使用即可。注册的位置不固定,只需要在项目中即可。

qRegisterMetaType<score>("score");

TIP:string也属于非基础类型数据

string相关的问题

由于string是std中的,因此就算包含了#incude头文件,在使用时也要加上std,例如:

std::string
std::to_string(int index)

否则会报错:

image-20240130224643754

代码

child_name.h

#include <QThread>]
#include<string>
struct score{
    int age;
    std::string name;
    int rate;
};

class child_name : public QThread
{
    Q_OBJECT //Q_OBJECT宏,使该类可以发送Qt信号
public:
    child_name();

signals:
    void send_index(score sc); //信号

protected:
    void run () override; //需要重写run方法
};

child_name.cpp

#include "child_name.h"
#include<stdlib.h>
#include<QDebug>
#include<string>
child_name::child_name() {}

void child_name::run(){
    while(1){
        //不间断的发送index,同时使index++
        score sc;
        sc.age = 13;
        sc.name="Tom";
        sc.rate = 100;
        emit this->send_index(sc);
        sleep(1); //每隔一秒发送
    }
}

Widget.h

#include <QWidget>
#include "child_name.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void handle_send_index(score score); //处理信号的槽函数
    void connectFunc();//专门绑定各槽函数
    child_name *child; //让子进程成为自己的成员,便于操作
public slots:
    void on_start_btn_clicked(); //按钮按下的槽函数

private:
    Ui::Widget *ui;
};

Widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "child_name.h"
#include<QString>
#include<string>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    qRegisterMetaType<score>("score");
    ui->setupUi(this);
    connectFunc();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::connectFunc(){
    //专门绑定各槽函数
    this->child = new child_name();
    connect(child,&child_name::send_index,this,&Widget::handle_send_index);
}

void Widget::handle_send_index(score sc){
    std::string str = "name: "+sc.name+"age: "+std::to_string(sc.age)+"rate: "+std::to_string(sc.rate);
    QString info = "index: "+QString::number(this->index++)+QString::fromStdString(str); //将int型转化为QString类型
    this->ui->dispInfo->clear(); //清除原有内容
    this->ui->dispInfo->setText(info);
}

void Widget::on_start_btn_clicked(){
    this->child->start(); //开始运行子进程
}

1.2 槽函数参数和信号参数的关系

Qt槽函数的参数需要和信号的参数保持一致,可以比信号的参数少,但是不能顺序不同,也不能比信号的参数多。

否则就会报错:
image-20240130230110816

1.3 重名信号的处理

例如,QCOmboBox里面的currentIndexChanged有两个重载的版本,而我们在使用QT5的connect时是只写函数名的,因此此时编译器会报错。

image-20240130230744196

若要处理,则使用Qt4的版本,因为它必须要指明参数的类型。例如

 connect(this->ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(handle_index_change(int));

此外,还可以采用泛型编程的思想:

connect(ui->comboBox, Q0verload<int>::of(&0comboBox::currentIndexchanged),this,&Widget::onIndex);

此时,QOverload的数据类型为int,则此时currentIndexChanged函数中参数列表就是int型的。反之,为QOverload<const QString&>时则函数参数列表为const QString&类型

1.4 connect函数

connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender //发送者的指针
Func1 signal, //信号
const QObject *contexct  //接收者的指针
Func2 slot, //槽函数
Qt::ConnectionType type = Qt::AutoConnection) //连接的类型默认为AutoConection

连接方式是枚举型,有以下几种连接方式:

enum ConnectionType {
        AutoConnection,
        DirectConnection,
        QueuedConnection,
        BlockingQueuedConnection,
        UniqueConnection =  0x80
    };

AutoConnection:默认的连接方式,如果接收方在发出信号的线程中,使用Qt::DirectConnection;否则使用Qt::Queuedconnection。使用这种方式,Qt在发出信号时确定连接类型。在Qt中默认是用的AutoConnection,所以平时写信号槽时都是4个参数。

DirectConnection:当发出信号时,插槽立即被调果难槽在发送信易的线程中执行。

QueuedConnection:当控制返回到接收方线程的事件循环时调用槽,槽在接收方的线程中执行。

BlockingQueuedConnection:与Qt::QueuedConnection相同,只是发送信号的线程会阻,直到返回如果接收方存在于发送信号的线程中,则不能使用此连接,否则应用程序将死锁。

UniqueConnection:这是一个可以使用按位OR与上述任何一种连接类型组合的标志,当Qt::UniqueConnection被设置时,如果连接已经存在,QObject::connect()将失败(例如,如果相同的信号已经连接到相同的对象对的插槽)。

2 总结

在代码的舞台上翩翩起舞, Qt,如诗如画,编织梦的彩虹。

跨越平台的轻盈舞姿, 文档的琴音,灵感的涟漪。

模块的花瓣,细腻而丰满, 开发者的心灵,在那里盛开。

清新而深邃,如林中明月, Qt,用优雅的笔触,谱写未来的篇章。

渴望挑战Qt的学习路径和掌握进阶技术?不妨点击下方链接,一同探讨更多Qt的奇迹吧。我们推出了引领趋势的💻QT专栏:《QT从基础到进阶》 ,旨在深度探索Qt的实际应用和创新。🌐🔍

在这里插入图片描述

在这里插入图片描述

  • 38
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在PyQt中,可以使用信号与槽机制来实现进程间的通信。PyQt信号与槽机制是基于Qt的,因此可以使用它来实现进程间的通信。 下面是一个示例代码,演示了如何在两个进程之间发送信号与槽: 进程1 - 发送信号进程: ```python from PyQt5.QtCore import QObject, pyqtSignal class SignalSender(QObject): my_signal = pyqtSignal(str) def send_signal(self, message): self.my_signal.emit(message) ``` 进程2 - 接收信号进程: ```python from PyQt5.QtCore import QObject, pyqtSlot class SignalReceiver(QObject): @pyqtSlot(str) def receive_signal(self, message): print("Received signal:", message) ``` 主程序: ```python from PyQt5.QtCore import QCoreApplication if __name__ == '__main__': app = QCoreApplication([]) sender = SignalSender() receiver = SignalReceiver() # 连接信号与槽 sender.my_signal.connect(receiver.receive_signal) # 发送信号 sender.send_signal("Hello from Process 1!") app.exec_() ``` 在上面的示例中,进程1(发送信号进程)定义了一个名为`SignalSender`的类,其中包含一个名为`my_signal`的信号。在`send_signal`方法中,通过调用`emit`函数来发送信号进程2(接收信号进程)定义了一个名为`SignalReceiver`的类,其中包含一个名为`receive_signal`的槽函数。通过使用`pyqtSlot`装饰器,将该函数标记为一个槽。 在主程序中,创建了一个`SignalSender`对象和一个`SignalReceiver`对象,并将它们的信号与槽连接起来。然后,通过调用`sender.send_signal`方法来发送信号。 当进程2接收到信号时,会调用`receive_signal`方法,并打印出接收到的消息。 请注意,以上示例是基于单个PyQt应用程序的进程通信。如果你希望在不同的进程中进行通信,可能需要使用更高级的通信机制,例如使用进程通信(IPC)的方法,如基于套接字的通信、共享内存、消息队列等。这些方法超出了PyQt的范围,需要使用其他库或方法来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值