首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Qt 實戰:自製 QQ 客戶端核心功能模塊(二)—— 好友列表與聊天窗口

     編輯:關於C語言

前言

承接上篇登錄模塊,本文講解基於 Qt + UDP 的好友列表面板、雙擊打開聊天窗口、消息收發顯示的核心實現。界面採用無邊框透明風格,通信協議自定義二進制流 (QDataStream)。

好友列表面板初始化

void Panel::init() {
    udpSocket = new QUdpSocket(this);
    udpSocket->bind(6666); // 綁定本地端口接收消息

    // 上線通知:MSG_CLIENT_NEW_CONN
    QString msgType = "MSG_CLIENT_NEW_CONN";
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_6);
    out << (quint16)0 << msgType << usrname; // 佔位長度、類型、用戶名
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16)); // 回填長度
    udpSocket->writeDatagram(block, QHostAddress(serverIp), serverPort+1);

    connect(udpSocket, &QUdpSocket::readyRead, this, &Panel::recvMsg);
}

列表項雙擊打開聊天窗口

void Panel::on_itemDoubleClicked(QListWidgetItem *item) {
    QString name = item->text().replace("\n", "");
    ChatForm *chat = chatHash.value(name);
    if (!chat) {
        chat = new ChatForm(usrname, serverIp, serverPort, udpSocket);
        chat->setWindowTitle("chatting with " + name);
        chatHash.insert(name, chat); // 緩存窗口,避免重複創建
    }
    chat->setWindowFlags(Qt::FramelessWindowHint);
    chat->setAttribute(Qt::WA_TranslucentBackground);
    chat->show();
}

聊天窗口消息顯示

void ChatForm::displayText(QString nickname, QString usrname, QString text) {
    QListWidgetItem *item = new QListWidgetItem(
        nickname + "(" + usrname + ") :\n" + text + "\n");
    ui->listWidget->addItem(item);
}

發送消息處理

void ChatForm::on_sendButton() {
    QString text = ui->textEdit->toPlainText();
    if (text.isEmpty()) return;

    // 解析窗口標題獲取目標用戶名
    QString title = windowTitle().replace("].", "");
    QString toId = title.split("[").at(1);

    QString msgType = "MSG_CLIENT_CHAT";
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_6);
    out << (quint16)0 << msgType << usrname << toId << text;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16)); // 回填包長

    udpSocket->writeDatagram(block, QHostAddress(serverIp), serverPort+1);

    // 本地回顯
    ui->listWidget->addItem("I say :\n" + text + "\n");
    ui->textEdit->clear();
}

界面效果圖

好友列表面板 聊天窗口

協議封包格式說明

[quint16 包總長度] [QString 消息類型] [QString 發送者] [QString 接收者] [QString 內容] ...
  • 長度字段佔 2 字節,不含自身,發送前 seek(0) 回填。
  • 所有字符串由 QDataStream 序列化 (長度前綴 + UTF-16 數據)。

關鍵設計點總結

  1. UDP 无連接特性:適合即時通訊,配合 bind() 固定端口接收。
  2. 窗口緩存 (QHash):同一好友雙擊多次不重複創建窗口。
  3. 無邊框透明窗口:FramelessWindowHint + WA_TranslucentBackground 實現自定義 UI。
  4. 本地回顯:發送後立即在本地列表顯示「I say」,體驗更流暢。

待優化項

  • 消息可靠性:UDP 丟包無重傳,生產環境需加序號 ACK 或改用 TCP/WebSocket。
  • 好友列表獲取:目前僅上線廣播,需服務端下發完整好友列表 (含狀態、頭像)。
  • 文件/圖片傳輸:大數據分片傳輸 + 進度條。
  • 加密:DTLS 或應用層 AES 加密。

下一篇將講解服務端監聽、數據庫存儲、廣播消息等後台邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved