一、简介
- QtDBus是一个使用D-Bus协议进行进程间通信的仅在Unix运行的库,是对D-Bus底层API的封装实现。
- QtDBus模块提供了使用Qt信号槽机制扩展的接口。
- 要使用QtDBus模块,需要在pro工程文件中增加下列代码来链接QtDBus库:
QT += qdbus
二、使用-收发消息
- 1、使用QDBusMessage发消息
- 发送代码:
QDBusMessage message =QDBusMessage::createSignal("/path", "com.message.test", "send_to_service");
message << "发送内容";
QDBusConnection::sessionBus().send(message);
- creatSignal中:
- ①"/path":对象路径
- ②"com.message.test":接口名称
- ③"send_to_service":方法名
- 这三个参数和下面QDBusConnection::sessionBus().connect()中参数对应
- 2 接收QDBusMessage发送的消息:
- 接收代码:
- 2.1 建立到session bus的连接:
QDBusConnection::sessionBus().connect(QString(), "/path", "com.message.test", "send_to_service",
this, SLOT(service_get(QString)));
- 2.2 接收消息处理:
void Widget::service_get(QString str)
{
ui->textBrowser->append(QString("接收消息:%1").arg(str));
}
- QDBusConnection::sessionBus().connect()中:
- ①QString():服务名,这里为空
- ②"/path":对象路径
- ③"com.message.test":接口名称
- ④"send_to_service":方法名
- ⑤this:接受者
- ⑥service_get(QString):槽函数
- 这几个参数和上面creatSignal中参数对应
三、使用-方法调用
- 1 server端在总线申请服务,供客户端调用
- 1.1 首先要在相应类中定义接口名称,com.widget.test.show为接口名称
Q_OBJECT
//定义Interface名称为com.widget.test.show
Q_CLASSINFO("D-Bus Interface", "com.widget.test.show")
- 1.2 然后要将方法放在public slots下
public slots:
int showmin();
int showmax();
int shownormal();
int hideclose();
- 1.3 最后建立到session bus的连接
//建立到session bus的连接
QDBusConnection connection = QDBusConnection::sessionBus();
//在session bus上注册名为com.widget.test的服务
if(!connection.registerService("com.widget.test"))
{
qDebug() << "error:" << connection.lastError().message();
exit(-1);
}
Widget w;//申请方法所在的类
//注册名为/test/objects的对象,把类Object所有槽函数导出为object的method
connection.registerObject("/test/objects", &w,QDBusConnection::ExportAllSlots);
w.show();
- 2 客户端调用服务方法
QDBusMessage message = QDBusMessage::createMethodCall("com.widget.test",
"/test/objects",
"com.widget.test.show",
method);
//发送消息
QDBusMessage res = QDBusConnection::sessionBus().call(message);
//判断method是否被正确返回
if (res.type() == QDBusMessage::ReplyMessage)
{
//从返回参数获取返回值
int value = res.arguments().takeFirst().toInt();
ui->textBrowser->append(QString("%1 返回值:%2").arg(method).arg(value));
}
else
{
ui->textBrowser->append(QString("%1 method called failed!").arg(str));
}
- ①服务名称为:com.widget.test
- ②对象路径为:/test/objects
- ③接口名称为:om.widget.test.show
- ④方法名称为:method
- 这里与上面server端建立的相关信息相对应
四、案例效果
五、关键代码
- 服务端
- widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
//定义Interface名称为com.widget.test.show
Q_CLASSINFO("D-Bus Interface", "com.widget.test.show")
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
int showmin();
int showmax();
int shownormal();
int hideclose();
private slots:
void on_pushButton_clicked();
void service_get(QString);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
- widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDBusMessage>
#include <QDBusConnection>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("QDBus-server");
move(100,100);
this->setWindowFlags(Qt::WindowStaysOnTopHint);
/* QDBusConnection::sessionBus().connect() 建立到session bus的连接,触发 service_get函数
* 参数1: 服务名称,这里为空
* 参数2:"/cpath" 对象路径
* 参数3:"com.message.test" 接口名称
* 参数4:"send_to_service" 方法名
* 参数5:this 消息接收者
*/
QDBusConnection::sessionBus().connect(QString(), "/path", "com.message.test", "send_to_service",
this, SLOT(service_get(QString)));
}
void Widget::on_pushButton_clicked()
{
/* "/path" : 对象路径
* "com.message.test" : 接口名称
* "send_to_control" : 方法名
* 这里参数和接收的地方 QDBusConnection::sessionBus().connect()参数对应
*/
QDBusMessage message =QDBusMessage::createSignal("/path", "com.message.test", "send_to_control");
message << ui->lineEdit->text();
QDBusConnection::sessionBus().send(message);
ui->textBrowser->append(QString("发送消息:%1").arg(ui->lineEdit->text()));
}
int Widget::showmin()
{
showMinimized();
ui->textBrowser->append("showmin 此方法被调用");
return 1;
}
int Widget::showmax()
{
showMaximized();
hide();
show();
ui->textBrowser->append("showmax 此方法被调用");
return 2;
}
int Widget::shownormal()
{
showNormal();
hide();
show();
ui->textBrowser->append("shownormal 此方法被调用");
return 3;
}
int Widget::hideclose()
{
close();
ui->textBrowser->append("hideclose 此方法被调用");
return 4;
}
void Widget::service_get(QString str)
{
ui->textBrowser->append(QString("接收消息:%1").arg(str));
}
Widget::~Widget()
{
delete ui;
}
- main.cpp
#include "widget.h"
#include <QApplication>
#include <QDBusConnection>
#include <QDebug>
#include <QDBusError>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//建立到session bus的连接
QDBusConnection connection = QDBusConnection::sessionBus();
//在session bus上注册名为com.widget.test的服务
if(!connection.registerService("com.widget.test"))
{
qDebug() << "error:" << connection.lastError().message();
exit(-1);
}
Widget w;
//注册名为/test/objects的对象,把类Object所有槽函数导出为object的method
connection.registerObject("/test/objects", &w,QDBusConnection::ExportAllSlots);
w.show();
return a.exec();
}
- 客户端
- widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_5_clicked();
void service_get(QString);
private:
void control(QString str);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
- widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowFlags(Qt::WindowStaysOnTopHint);
this->setWindowTitle("QDBus-control");
connect(ui->pushButton,&QPushButton::clicked,this,[=](){
control("hideclose");
});
connect(ui->pushButton_2,&QPushButton::clicked,this,[=](){
control("showmin");
});
connect(ui->pushButton_3,&QPushButton::clicked,this,[=](){
control("shownormal");
});
connect(ui->pushButton_4,&QPushButton::clicked,this,[=](){
control("showmax");
});
/* QDBusConnection::sessionBus().connect() 建立到session bus的连接,触发 service_get函数
* 参数1: 服务名称,这里为空
* 参数2:"/path" 对象路径
* 参数3:"com.message.test" 接口名称
* 参数4:"send_to_service" 方法名
* 参数5:this 消息接收者
*/
QDBusConnection::sessionBus().connect(QString(), "/path", "com.message.test", "send_to_control",
this, SLOT(service_get(QString)));
}
void Widget::control(QString method)
{
/* 造一个method_call消息
* 服务名称为:com.widget.test
* 对象路径为:/test/objects
* 接口名称为:om.widget.test.show,
* 方法名称为:method
*/
QDBusMessage message = QDBusMessage::createMethodCall("com.widget.test",
"/test/objects",
"com.widget.test.show",
method);
//发送消息
QDBusMessage res = QDBusConnection::sessionBus().call(message);
//判断method是否被正确返回
if (res.type() == QDBusMessage::ReplyMessage)
{
//从返回参数获取返回值
int value = res.arguments().takeFirst().toInt();
ui->textBrowser->append(QString("%1 返回值:%2").arg(method).arg(value));
}
else
{
ui->textBrowser->append(QString("%1 method called failed!").arg(method));
}
}
void Widget::service_get(QString str)
{
ui->textBrowser->append(QString("接收消息:%1").arg(str));
}
void Widget::on_pushButton_5_clicked()
{
/* "/path" : 对象路径
* "com.message.test" : 接口名称
* "send_to_control" : 方法名
* 这里参数和接收的地方 QDBusConnection::sessionBus().connect()参数对应
*/
QDBusMessage message =QDBusMessage::createSignal("/path", "com.message.test", "send_to_service");
message << ui->lineEdit->text();
QDBusConnection::sessionBus().send(message);
ui->textBrowser->append(QString("发送消息:%1").arg(ui->lineEdit->text()));
}
Widget::~Widget()
{
delete ui;
}
- main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}