首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Qt | linux dbus聊天

Qt | linux dbus聊天

原创
作者头像
Qt历险记
发布2024-12-22 17:06:49
发布2024-12-22 17:06:49
1.9K0
举报
文章被收录于专栏:Qt6 研发工程师Qt6 研发工程师

点击上方"蓝字"关注我们

01、Qt6::DBus

>>>Qt6::DBus 是 Qt 6 中用于实现 D-Bus(Desktop Bus)通信的模块。D-Bus 是一种消息总线系统,用于在同一台计算机上的不同进程之间进行通信,非常常用于 Linux 环境中的应用程序之间的交互。

Qt6.5.3

ubuntu22.04

02、QInputDialog

>>>QInputDialog 是 Qt 中用于显示输入对话框的一个类,允许用户通过简单的输入框来输入数据。您可以使用 QInputDialog 来获取字符串、整数、浮点数等类型的输入。

03、QDBusConnection

>>> QDBusConnection 是 Qt 中与 D-Bus(Desktop Bus)协议交互的类。D-Bus 是一种用于在同一台计算机上不同进程之间进行通信的系统,广泛用于 Linux 环境。 QDBusConnection 的基本功能 QDBusConnection 提供了对 D-Bus 连接的管理,包括发送信号、调用远程方法、注册对象等功能。它的主要成员包括:

  1. sessionBus():获取到会话总线连接,这是大多数桌面应用程序使用的 D-Bus 连接。
  2. systemBus():获取到系统总线连接,通常用于系统范围的消息传递。
  3. registerObject():将对象注册到 D-Bus,以使其可以被其他进程访问。
  4. send():发送 D-Bus 消息。
  5. connect():连接 D-Bus 信号到槽函数。

04、QDBusAbstractAdaptor

>>>QDBusAbstractAdaptor 是 QtDBus 模块中的一个类,用于创建 D-Bus 适配器。适配器的主要目的是将 C++ 对象的信号和槽映射到 D-Bus 方法和信号,从而使得 C++ 对象可以通过 D-Bus 被外部进程访问。

04、ChatAdaptor

>>>在 Qt 中,new ChatAdaptor(this) 通常用于创建一个 D-Bus 适配器的实例,以便将当前对象(在上下文中通常是一个聊天窗口对象)与 D-Bus 进行连接。适配器类通常是继承自 QDBusAbstractAdaptor,它简化了方法和信号的暴露过程,使其他通过 D-Bus 的客户端能够访问该对象的功能。

05、using org::example::chat

>>>在 C++ 中,using org::example::chat; 是一种命名空间的使用声明。这行代码的目的是在当前作用域中引入 org::example::chat 命名空间,以便可以更方便地访问该命名空间中的类、方法或其他成员,而无需每次都写出完整的命名空间路径。

07、CMakeLists.txt

>>>

代码语言:javascript
复制
# 设置 CMake 最小版本要求cmake_minimum_required(VERSION 3.16)# 声明项目名称和使用的编程语言project(chat LANGUAGES CXX)​# 包含当前目录set(CMAKE_INCLUDE_CURRENT_DIR ON)​# 如果未定义安装示例目录,则设置默认值if(NOT DEFINED INSTALL_EXAMPLESDIR)    set(INSTALL_EXAMPLESDIR "examples")endif()​# 设置安装示例目录的路径set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/dbus/chat")​# 查找 Qt6 的所需组件find_package(Qt6 REQUIRED COMPONENTS Core DBus Gui Widgets)​# 设置 Qt 标准项目qt_standard_project_setup()​# 定义一个源文件列表set(chat_SRCS)# 添加 D-Bus 接口文件和生成的源文件qt_add_dbus_interface(chat_SRCS    org.example.chat.xml    chat_interface)​# 添加 D-Bus 适配器qt_add_dbus_adaptor(chat_SRCS    org.example.chat.xml    qobject.h    QObject    chat_adaptor)​# 创建可执行文件,包含源文件和 UI 文件qt_add_executable(chat    chat.cpp ChatMainWindow.h    chatmainwindow.ui    ${chat_SRCS})​# 设置目标属性,确保在 Windows 和 macOS 上以合适的方式构建set_target_properties(chat PROPERTIES    WIN32_EXECUTABLE TRUE    MACOSX_BUNDLE TRUE)​# 指定链接库target_link_libraries(chat PRIVATE    Qt6::Core    Qt6::DBus    Qt6::Gui    Qt6::Widgets)​# 安装目标设置install(TARGETS chat    RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"  # 安装运行时文件    BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"   # 安装捆绑文件    LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"  # 安装库文件)​

08、ChatMainWindow.h

>>>

代码语言:javascript
复制
#ifndef CHATMAINWINDOW_H#define CHATMAINWINDOW_H​// 引入 QStringList 类头文件,用于存储消息列表#include <QStringList>​// 引入自动生成的用户界面头文件#include "ui_chatmainwindow.h"​// 定义 ChatMainWindow 类,继承自 QMainWindow 和 Ui::ChatMainWindowclass ChatMainWindow: public QMainWindow, Ui::ChatMainWindow{    Q_OBJECT // 此宏用于启用 Qt 的信号和槽机制​    // 成员变量:存储用户昵称    QString m_nickname;​    // 成员变量:存储聊天消息的列表    QStringList m_messages;​public:    // 构造函数,初始化聊天主窗口    ChatMainWindow();​private:    // 私有方法:用于显示一条消息    void displayMessage(const QString &message);​signals:    // 信号:发送消息,包含昵称和消息文本    void message(const QString &nickname, const QString &text);​    // 信号:执行某个动作,包含昵称和消息文本    void action(const QString &nickname, const QString &text);​private slots:    // 私有槽:用于更改昵称,可以传入初始值参数    bool changeNickname(bool initial = false);};​#endif // CHATMAINWINDOW_H​

09、chat.cpp

>>>

代码语言:javascript
复制
#include <QApplication>       // 引入 QApplication 类,用于管理应用程序的控制流和主要设置#include <QInputDialog>       // 引入 QInputDialog 类,用于弹出输入对话框#include <QMessageBox>        // 引入 QMessageBox 类,用于显示消息框​#include "ChatMainWindow.h"   // 引入自定义的聊天主窗口类头文件#include "chat_adaptor.h"     // 引入 D-Bus 适配器类头文件#include "chat_interface.h"   // 引入 D-Bus 接口类头文件​// ChatMainWindow 构造函数ChatMainWindow::ChatMainWindow(){    setupUi(this); // 设置用户界面,通过 Qt Designer 生成的代码初始化 UI​    // 连接信号和槽,当文本框内容变化时,更新发送按钮的可用状态    connect(messageLineEdit, &QLineEdit::textChanged, this,            [this](const QString &newText) { sendButton->setEnabled(!newText.isEmpty()); });​    // 连接“发送”按钮的点击事件,发送消息,并清空输入框    connect(sendButton, &QPushButton::clicked, this, [this]() {        emit message(m_nickname, messageLineEdit->text()); // 发出消息信号        messageLineEdit->clear(); // 清空输入框    });​    // 连接“更改昵称”的触发事件,调用 changeNickname 方法    connect(actionChangeNickname, &QAction::triggered,            this, &ChatMainWindow::changeNickname);​    // 连接“关于 Qt”的触发事件,显示有关 Qt 的信息框    connect(actionAboutQt, &QAction::triggered, this, [this]() { QMessageBox::aboutQt(this); });​    // 连接应用程序最后一个窗口关闭的信号,发出用户退出聊天的动作信号    connect(qApp, &QApplication::lastWindowClosed, this,            [this]() { emit action(m_nickname, tr("退出聊天")); });​    // 添加 D-Bus 接口并连接到 D-Bus    new ChatAdaptor(this); // 创建 D-Bus 适配器对象​    auto connection = QDBusConnection::sessionBus(); // 获取会话总线连接    // "/": 在这里,"/" 是该对象在 D-Bus 上的路径。D-Bus 采用树形结构来组织对象,每个对象都有其唯一的路径。使用根路径 "/" 意味着该对象将注册为系统的顶层对象。    connection.registerObject("/", this); // 注册对象,使其可通过 D-Bus 访问​    // using chat = ::OrgExampleChatInterface;: 这行代码通过 using 声明创建了一个别名。    // chat 现在可以作为 ::OrgExampleChatInterface 的别名。这意味着在后续代码中,可以用 org::example::chat 来引用 OrgExampleChatInterface 类,    // 而不需要每次都写出完整的命名空间路径。    using org::example::chat; // 使用命名空间​    // 创建并初始化 D-Bus 接口对象    // OrgExampleChatInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);    auto *iface = new chat({}, {}, connection, this);​    // 连接 D-Bus 消息信号    connect(iface, &chat::message, this, [this](const QString &nickname, const QString &text) {        displayMessage(tr("<%1> %2").arg(nickname, text)); // 显示消息    });​    // 连接 D-Bus 动作信号    connect(iface, &chat::action, this, [this](const QString &nickname, const QString &text) {        displayMessage(tr("* %1 %2").arg(nickname, text)); // 显示动作    });​    // 尝试更改昵称,若失败则退出应用程序    if (!changeNickname(true))        QMetaObject::invokeMethod(qApp, &QApplication::quit, Qt::QueuedConnection); // 退出应用程序}​// 显示消息的方法void ChatMainWindow::displayMessage(const QString &message){    m_messages.append(message); // 将新消息添加到消息列表​    // 保持消息数量在 100 条以内,超过则删除最旧消息    if (m_messages.count() > 100)        m_messages.removeFirst();​    // 将消息列表合并为一个字符串,在聊天记录文本框中显示    auto history = m_messages.join(QLatin1String("\n"));    chatHistory->setPlainText(history); // 更新聊天记录显示}​// 更改昵称的方法bool ChatMainWindow::changeNickname(bool initial){    auto newNickname = QInputDialog::getText(this, tr("设置昵称"), tr("新昵称:")); // 弹出输入对话框    newNickname = newNickname.trimmed(); // 去除首尾空格​    if (!newNickname.isEmpty()) { // 如果昵称不为空        auto old = m_nickname; // 保存旧昵称        m_nickname = newNickname; // 更新为新昵称​        // 根据是否是初始昵称,发出相应的动作信号        if (initial)            emit action(m_nickname, tr("加入聊天")); // 新用户加入聊天        else            emit action(old, tr("现在被称为 %1").arg(m_nickname)); // 更新用户昵称        return true; // 返回成功    }​    return false; // 返回失败}​// 主函数int main(int argc, char **argv){    QApplication app(argc, argv); // 创建应用程序对象​    // 检查 D-Bus 会话总线连接    if (!QDBusConnection::sessionBus().isConnected()) {        qWarning("无法连接到D-Bus会话总线。\n"                 "请检查您的系统设置,然后重试。\n"); // 输出警告信息        return 1; // 返回错误代码    }​    ChatMainWindow chat; // 创建聊天主窗口对象    chat.show(); // 显示该窗口    return app.exec(); // 进入应用程序主事件循环}​

10、chatmainwindow.ui

>>>

总结和演示

>>>1,演示

2,运行

【源码】记得转存慢慢看 通过网盘分享的文件:chat 链接: https://pan.baidu.com/s/1pKsDTVsaQFswjy6FQlSrKw?pwd=qt93 提取码: qt93

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 点击上方"蓝字"关注我们
  • 01、Qt6::DBus
  • Qt6.5.3
  • 02、QInputDialog
  • 03、QDBusConnection
  • 04、QDBusAbstractAdaptor
  • 04、ChatAdaptor
  • 05、using org::example::chat
  • 07、CMakeLists.txt
  • 08、ChatMainWindow.h
  • 09、chat.cpp
  • 10、chatmainwindow.ui
  • 总结和演示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档