QtRemoteObjects WebSockets アプリケーション

QtRemoteObjectsQIODevice 以外のトランスポート (QWebSocket) を使う。

この例では、QStandardItemModel を Web ソケットで共有しています。モデルはwsserver アプリケーションのウィンドウで編集することができ、その変更はwsclient アプリケーションのウィンドウに反映されます。

これは、QWebSocket 用に小さなQIODevice 由来のラッパーWebSocketIoDevice を実装することで可能になります。QtがSSLをサポートしてコンパイルされている場合、SSLが使用されます。

WsServerアプリケーション

wsserver アプリケーションは2つのカラムを持つQStandardItemModel を作成し、そこにデータを挿入します。

int main(int argc, char *argv[])
{
    QLoggingCategory::setFilterRules("qt.remoteobjects.debug=false\n"
                                     "qt.remoteobjects.warning=false");
    QApplication app(argc, argv);

    const int modelSize = 100000;
    QStringList list;
    QStandardItemModel sourceModel;
    QStringList hHeaderList;
    hHeaderList << QStringLiteral("First Column with spacing") << QStringLiteral("Second Column with spacing");
    sourceModel.setHorizontalHeaderLabels(hHeaderList);
    list.reserve(modelSize);
    for (int i = 0; i < modelSize; ++i) {
        QStandardItem *firstItem = new QStandardItem(QStringLiteral("FancyTextNumber %1").arg(i));
        if (i == 0)
            firstItem->appendRow(addChild(2, 2));
        QStandardItem *secondItem = new QStandardItem(QStringLiteral("FancyRow2TextNumber %1").arg(i));
        if (i % 2 == 0)
            firstItem->setBackground(Qt::red);
        QList<QStandardItem*> row;
        row << firstItem << secondItem;
        sourceModel.invisibleRootItem()->appendRow(row);
        //sourceModel.appendRow(row);
        list << QStringLiteral("FancyTextNumber %1").arg(i);
    }

そして、ポート8088にバインドされたQWebSocketServer を起動し、データモデルをホストします。

QWebSocketServer webSockServer{QStringLiteral("WS QtRO"), QWebSocketServer::NonSecureMode};
webSockServer.listen(QHostAddress::Any, 8088);

QRemoteObjectHost hostNode;
hostNode.setHostUrl(webSockServer.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);

hostNode.enableRemoting(&sourceModel, QStringLiteral("RemoteModel"), roles);

新しい接続を処理するとき、QtがSSLをサポートしてコンパイルされていれば、SSLが設定されます。その後、WebSocketServer 接続を使用してWebSocketIoDevice が作成されます。

QObject::connect(&webSockServer, &QWebSocketServer::newConnection, &hostNode, [&hostNode, &webSockServer]{while(autoconn=webSockServer.nextPendingConnection()) {#ifndef QT_NO_SSL // 利用可能な場合は常にセキュアな接続を使用しますQSslConfigurationsslConf;        QFilecertFile(QStringLiteral(":/sslcert/server.crt"));if(!certFile.open(QIODevice::ReadOnly))            qFatal("Can't open client.crt file");
        sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()});        QFilekeyFile(QStringLiteral(":/sslcert/server.key"));if(!keyFile.open(QIODevice::ReadOnly))            qFatal("Can't open client.key file");
        sslConf.setPrivateKey(QSslKey{keyFile.readAll()QSsl::Rsa}); sslConf.setPeerVerifyMode(QSslSocketconn->setSslConfiguration(sslConf);        QObject::connect(conn, &QWebSocket::sslErrors,conn, &QWebSocket::deleteLater);#endif     QObject::connect(conn, &QWebSocket::disconnected,conn, &QWebSocket::deleteLater);        QObject::connect(conn, &QWebSocket::errorOccurred,conn, &QWebSocket::deleteLater);autoioDevice= newWebSocketIoDevice(conn);        QObject::connect(conn, &QWebSocket::destroyed,ioDevice, &WebSocketIoDevice::deleteLater); hostNode.addHostSideConnection(ioDevice); } });

QStandardItemModel をモデルとして QTreeView を作成します。その後、QTimer::singleShot で複数のタイマが起動され、モデルの修正が行われる。

QTreeView view;
view.setWindowTitle(QStringLiteral("SourceView"));
view.setModel(&sourceModel);
view.show();
TimerHandler handler;
handler.model = &sourceModel;
QTimer::singleShot(5000, &handler, &TimerHandler::changeData);
QTimer::singleShot(10000, &handler, &TimerHandler::insertData);
QTimer::singleShot(11000, &handler, &TimerHandler::changeFlags);
QTimer::singleShot(12000, &handler, &TimerHandler::removeData);
QTimer::singleShot(13000, &handler, &TimerHandler::moveData);

return app.exec();

WsClientアプリケーション

wsclient アプリケーションはQWebSocketを作成し、それを引数としてWebSocketIoDevice

QScopedPointer<QWebSocket> webSocket{new QWebSocket};
WebSocketIoDevice socket(webSocket.data());

QtがSSLをサポートしてコンパイルされている場合、クライアントはSSLで設定されます。

#ifndef QT_NO_SSL // 利用可能な場合は常に安全な接続を使用するQSslConfigurationsslConf;    QFilecertFile(QStringLiteral(":/sslcert/client.crt"));if(!certFile.open(QIODevice::ReadOnly))        qFatal("Can't open client.crt file");
    sslConf.setLocalCertificate(QSslCertificate{certFile.readAll()});    QFilekeyFile(QStringLiteral(":/sslcert/client.key"));if(!keyFile.open(QIODevice::ReadOnly))        qFatal("Can't open client.key file");
    sslConf.setPrivateKey(QSslKey{keyFile.readAll()QSsl::Rsa}); sslConf.setPeerVerifyMode(QSslSocket::VerifyPeer); webSocket->setSslConfiguration(sslConf);#endif

次に、QRemoteObjectNode が作成され、WebSocketIoDevice を使用するように設定される。そして、wsserver に接続する。

QRemoteObjectNode node;
node.addClientSideConnection(&socket);
node.setHeartbeatInterval(1000);
webSocket->open(QStringLiteral("ws://localhost:8088"));

サーバーからのデータを表示するためにQTreeViewが作成されます。モデルはノードから取得され、QTreeView のモデルとして設定され、表示されます。

QTreeView view;
view.setWindowTitle(QStringLiteral("RemoteView"));
view.resize(640,480);
QScopedPointer<QAbstractItemModelReplica> model(node.acquireModel(QStringLiteral("RemoteModel")));
view.setModel(model.data());
view.show();

return app.exec();

プロジェクト例 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.