示例 1:使用静态源进行直接连接
- 创建源对象
要创建此 Source 对象,首先我们创建定义文件,
simpleswitch.rep
。此文件描述对象的属性和方法,并将其输入 Qt 远程对象编译器 repc。此文件仅定义了必须暴露给 Replicas 的接口。simpleswitch.rep
class SimpleSwitch { PROP(bool currState=false); SLOT(server_slot(bool clientState)); };
在
simpleswitch.rep
中,currState
存储开关的当前状态。server_slot()
允许我们与源进行交互 - 它将连接到echoSwitchState(bool newstate)
信号。
对于 repc 处理此文件,请将以下行添加到您的
cmake
文件中qt6_add_repc_sources(directconnectserver simpleswitch.rep )
如果您正在使用
qmake
REPC_SOURCE = simpleswitch.rep
这些说明仅适用于 Qt 远程对象模块,因此您还需要将其添加到项目中。如果您正在使用 CMake,请添加
find_package(Qt6 REQUIRED COMPONENTS RemoteObjects) target_link_libraries(directconnectserver PRIVATE Qt6::RemoteObjects)
如果您正在使用
qmake
QT += remoteobjects
repc 在您指定的构建目录中创建了
rep_SimpleSwitch_source.h
头文件。有关更多信息,请参阅 Source。repc 为使用 QtRO 创建了三个辅助类。对于此示例,我们使用基本类:
SimpleSwitchSimpleSource
。它是一个抽象类,在rep_SimpleSwitch_source.h
中定义。我们从中派生出自定义 SimpleSwitch 实现类,如下所示simpleswitch.h
#ifndef SIMPLESWITCH_H #define SIMPLESWITCH_H #include "rep_simpleswitch_source.h" class SimpleSwitch : public SimpleSwitchSimpleSource { Q_OBJECT public: SimpleSwitch(QObject *parent = nullptr); ~SimpleSwitch(); void server_slot(bool clientState) override; public Q_SLOTS: void timeout_slot(); private: QTimer *stateChangeTimer; }; #endif
在
simpleswitch.h
中,stateChangeTimer
是一个 QTimer,用于切换 SimpleSwitch 的状态。timeout_slot()
连接到stateChangeTimer
的 timeout() 信号。server_slot()
– 当副本调用其槽的版本时在源上自动调用 – 输出接收到的值。currStateChanged(bool)
,在由 repc 生成的rep_SimpleSwitch_source.h
中定义,每当currState
切换时都会发出。在此示例中,我们忽略源端的信号,稍后在副本端处理。
我们的
SwitchState
类的定义如下所示simpleswitch.cpp
#include "simpleswitch.h" // constructor SimpleSwitch::SimpleSwitch(QObject *parent) : SimpleSwitchSimpleSource(parent) { stateChangeTimer = new QTimer(this); // Initialize timer QObject::connect(stateChangeTimer, &QTimer::timeout, this, &SimpleSwitch::timeout_slot); // connect timeout() signal from stateChangeTimer to timeout_slot() of simpleSwitch stateChangeTimer->start(2000); // Start timer and set timout to 2 seconds qDebug() << "Source Node Started"; } //destructor SimpleSwitch::~SimpleSwitch() { stateChangeTimer->stop(); } void SimpleSwitch::server_slot(bool clientState) { qDebug() << "Replica state is " << clientState; // print switch state echoed back by client } void SimpleSwitch::timeout_slot() { // slot called on timer timeout if (currState()) // check if current state is true, currState() is defined in repc generated rep_simpleswitch_source.h setCurrState(false); // set state to false else setCurrState(true); // set state to true qDebug() << "Source State is "<<currState(); }
- 创建注册表
由于此示例使用节点之间的直接连接,因此我们可以省略此步骤。
- 创建主机节点
主机节点创建如下所示
QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica")));
- 主机源对象和远程调用
以下语句实例化了 Source 对象,并将其传递给主机以启用“远程调用”,这是使对象对 QtRO 网络可见的过程
SimpleSwitch srcSwitch; // create simple switch srcNode.enableRemoting(&srcSwitch); // enable remoting
以上步骤所实现的
main.cpp
文件内容如下main.cpp
#include <QCoreApplication> #include "simpleswitch.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); SimpleSwitch srcSwitch; // create simple switch // Create host node without Registry: QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica"))); srcNode.enableRemoting(&srcSwitch); // enable remoting/sharing return a.exec(); }
编译并运行此源端项目。在没有创建任何副本的情况下,输出应该如下所示,开关状态在每两秒内切换一次
true
和false
。
以下步骤用于创建网络副本端,在这个例子中,从 源 获取开关状态并将其回显。
副本代码
- 使用 repc 向您的项目中添加副本
我们使用与源端相同的 API 定义文件
SimpleSwitch.rep
,使用 repc 创建一个 副本 头文件。如果您使用cmake
,请在客户端cmake
文件中包含以下行,指定.rep
文件输入qt6_add_repc_replicas(directconnectclient simpleswitch.rep )
如果您使用
qmake
,将以下行添加到客户端.pro
文件中REPC_REPLICA = simpleswitch.rep
repc 工具在构建目录中生成一个
rep_SimpleSwitch_replica.h
文件。有关更多信息,请参阅 副本。 - 创建一个节点来连接到源的主节点
以下代码实例化了网络上的第二个节点并将其连接到源主节点
QRemoteObjectNode repNode; // create remote object node repNode.connectToNode(QUrl(QStringLiteral("local:replica"))); // connect with remote host node
- 调用节点的 acquire() 以创建一个副本的指针
首先,我们实例化一个副本
QSharedPointer<SimpleSwitchReplica> ptr; ptr.reset(repNode.acquire<SimpleSwitchReplica>()); // acquire replica of source from host node
注意:acquire() 返回一个指向副本的指针,但不管理其生命周期。此示例展示了将返回的指针包裹在 QSharedPointer 或 QScopedPointer 中的建议流程,以确保总是正确删除指针。
main.cpp
实现了上述步骤并实例化了我们的对象main.cpp
#include <QCoreApplication> #include "client.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSharedPointer<SimpleSwitchReplica> ptr; // shared pointer to hold source replica QRemoteObjectNode repNode; // create remote object node repNode.connectToNode(QUrl(QStringLiteral("local:replica"))); // connect with remote host node ptr.reset(repNode.acquire<SimpleSwitchReplica>()); // acquire replica of source from host node Client rswitch(ptr); // create client switch object and pass reference of replica to it return a.exec(); }
Client
类的完整声明和定义如下client.h
#ifndef _CLIENT_H #define _CLIENT_H #include <QObject> #include <QSharedPointer> #include "rep_simpleswitch_replica.h" class Client : public QObject { Q_OBJECT public: Client(QSharedPointer<SimpleSwitchReplica> ptr); ~Client() override = default; void initConnections();// Function to connect signals and slots of source and client Q_SIGNALS: void echoSwitchState(bool switchState);// this signal is connected with server_slot(..) on the source object and echoes back switch state received from source public Q_SLOTS: void recSwitchState_slot(bool); // slot to receive source state private: bool clientSwitchState; // holds received server switch state QSharedPointer<SimpleSwitchReplica> reptr;// holds reference to replica }; #endif
client.cpp
#include "client.h" // constructor Client::Client(QSharedPointer<SimpleSwitchReplica> ptr) : QObject(nullptr),reptr(ptr) { // Connect signal for replica initialized with initialization slot. initConnections(); // We can connect to SimpleSwitchReplica Signals/Slots // directly because our Replica was generated by repc. } void Client::initConnections() { // initialize connections between signals and slots // connect source replica signal currStateChanged() with client's recSwitchState() slot to receive source's current state QObject::connect(reptr.data(), &SimpleSwitchReplica::currStateChanged, this, &Client::recSwitchState_slot); // connect client's echoSwitchState(..) signal with replica's server_slot(..) to echo back received state QObject::connect(this, &Client::echoSwitchState, reptr.data(), &SimpleSwitchReplica::server_slot); } void Client::recSwitchState_slot(bool value) { qDebug() << "Received source state "<< value << reptr.data()->currState(); clientSwitchState = reptr.data()->currState(); Q_EMIT echoSwitchState(clientSwitchState); // Emit signal to echo received state back to server }
编译并运行此示例,连同源端示例一起生成以下输出
© 2024 The Qt Company Ltd. 本文档内的文档贡献是它们各自所有者的版权。本提供的文档根据 Free Software Foundation 发布的 GNU Free Documentation License 1.3 版本 的条款许可。Qt 及相关标志是 The Qt Company Ltd. 在芬兰及和/或全球其他国家的商标。所有其他商标归其各自所有者所有。