天天看點

基于QT的UDP網絡聊天室(QQ界面)

QT網絡聊天室(udp)

1.第一部分界面部分

基于QT的UDP網絡聊天室(QQ界面)

第一部分的QT(QQ)界面部分的控件分别有登入是一個button類用于發送登入資訊

lineEdit類用于接收使用者名,還有一些裝飾的小控件具體請看UI檔案

首先1.我們實作了一個根據滑鼠滑動可以拖動主視窗的功能

二。第二部分視窗滑動事件

使用滑鼠拖動事件與滑鼠按壓事件的一個互動請注意這裡的按壓點應該減去我們的滑鼠中心點達到一個拖動視窗而不更換視窗位子的現象

用到了

QMouseEvent Qpoint 類分别用于處理滑鼠事件和得到一個坐标點

在這裡插入代碼片
void Widget::mousePressEvent(QMouseEvent *event)
{
#if 0
    qDebug() << event->pos();//滑鼠在窗體上的坐标,窗體的坐标原點在窗體的左上角
    qDebug() << event->globalPos();//滑鼠相對于螢幕坐标系的坐标
    qDebug() << this->pos();//窗體在螢幕上面的坐标
#endif
   mousePressPoint = event->pos();
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
#if 0
    qDebug() << event->pos();//滑鼠在窗體上的坐标,窗體的坐标原點在窗體的左上角
    qDebug() << event->globalPos();//滑鼠相對于螢幕坐标系的坐标
    qDebug() << this->pos();//窗體在螢幕上面的坐标
#endif
    this->move(event->globalPos() - mousePressPoint);
}
           

三。UDP按鈕發送部分

既然是UDP通信在QT中自然有與之相關的類如 QUdpSocket建立一個套接字用于udp通信我們在開始用Qudosocket建立對象後通過連接配接botton 的槽函數用json包的形式發送json資料包首先定義為一個json對象插入資料後在裝換為jsondcument對象再用tojson()函數轉換為QArray數組對象

//登入界面的槽函數
void Widget::on_pushButton_clicked()
{
    chatWindow->setUsername(ui->lineEdit->text());
    chatWindow->show();
    broadcastLoginMessage();
    this->close();
    
}
//發送json包的函數用udpdatawrite函數寫入資料
void Widget::broadcastLoginMessage()
{
    QJsonObject jsonObject;

    jsonObject.insert("message_type",1);
    jsonObject.insert("name",ui->lineEdit->text());
    jsonObject.insert("content","I am login");
    //jsonObject.insert("port",8888);//聊天界面的套接字端口号
    jsonObject["port"] = 8888;


    //将jsonObject轉成json格式的資料
    QJsonDocument jsondoc(jsonObject);
    QByteArray jsonData = jsondoc.toJson();

    udpSocket->writeDatagram(jsonData,QHostAddress(QHostAddress::Broadcast),8888);
}
           

登入端主函數結束

第四部分第二視窗收端

首先我們要在收做的是建立一個Qudpsocket對象用bild函數綁定自己的端口并且連接配接一個信号,當有人給我發包的時候系統自動調用recvread函數進而進入下一個階段

在這裡插入代碼片
destIP = "255.255.255.0";
    destport=8888;

    udpSocket = new QUdpSocket(this);
    bool ok = udpSocket->bind(8888);
    if(!ok){
        qDebug() << "Fail to bind port:8888 , error:" << udpSocket->errorString();
        return;
    }

     connect(udpSocket,SIGNAL(readyRead()),this,SLOT(recvMessage()));
}
           

第五部分接受函數在一個循環體中使用readData函數将剛才發送的函數進來接受并交給一個函數出統一處理

void ChatWindow::recvMessage()
{
    //讀取資料
    while (udpSocket->hasPendingDatagrams()) {

        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;

        udpSocket->readDatagram(datagram.data(), datagram.size(),
                                &sender, &senderPort);
//接受到信号後将進去轉換json函數中之中我們傳入我們的資料,IP位址 端口号
        processTheDatagram(datagram,sender,senderPort);
    }

    return;
}
           

第六部分在處理函數中解析并根據發資料包的不同來作用于不同的功能剛開始的值為1直接跳入來listwiget中發廣播包

void ChatWindow::processTheDatagram(const QByteArray &data,const QHostAddress &sender,
                                    const int senderPort)
{
    //将我們的接收到的json包借讀根據不同的message_type值來選擇相應的類容
     QJsonParseError parseError;
     qDebug()<<senderPort;
     QJsonDocument jsondoc = QJsonDocument::fromJson(data,&parseError);
     if(jsondoc.isNull() || parseError.error != QJsonParseError::NoError){
         qDebug() << "Fail to parse json data : " << parseError.errorString();
         return;
     }
     QJsonObject jsonObject = jsondoc.object();
     int message_type = jsonObject["message_type"].toInt();
     QString name     = jsonObject["name"].toString();
     QString content  = jsonObject["content"].toString();
     short  port      = (short)jsonObject["port"].toInt();

     switch(message_type){
     case ChatWindow::LOGIN_MESSAGE:
         //添加登陸的使用者到好友清單
         //給登陸的使用者發送一個應答消息,告訴他自己線上
         doUserLogin(QHostAddress(sender.toIPv4Address()),name,port);
         break;

     case ChatWindow::CHAT_MESSAGE:
         //顯示聊天的消息
         break;

     case ChatWindow::ACK_MESSAGE:
         //添加應答使用者到好友清單
         doUserAck(QHostAddress(sender.toIPv4Address()),name,port);
         return;

     case ChatWindow::QUIT_MESSAGE:
         //将退出的使用者從好友清單中删除
         doUserQuit(QHostAddress(sender.toIPv4Address()),name,port);
         break;

     }
       displaySendChatMessage(username,content);

     return;
}
           

第七部沒法來一個包就将自己的資訊加入清單中,加一判斷,如果是自己的則不用,如果不是則告訴其他使用者

void ChatWindow::addUserToList(const QHostAddress &ip, const QString &name, short port)
{
    QString text = QString("%1\n%2:%3").arg(name).arg(ip.toString()).arg(port);
    //一種輸出文本格式可以相當于printf
    ui->listWidget->addItem(new QListWidgetItem(QIcon(":/image/HeadImage.png"),text));
    //加圖檔在listWidget中去
    ui->listWidget->setIconSize(QSize(50,50));
    //設定圖檔的大小
    return;
    //實作了将list上加一個元素
}
//将我們
void ChatWindow::tellLoginUser(const QHostAddress &destIp,const short destPort)
{ //不是自己發的包就要給所有人發一個告知包我上線了
    QJsonObject jsonObject;
    jsonObject.insert("message_type",ChatWindow::ACK_MESSAGE);
   //發送應答型号之後跳到應答函數裡面
    jsonObject.insert("name",username);
    jsonObject["port"] = 8888;
    //将jsonObject轉成json格式的資料
    QJsonDocument jsondoc(jsonObject);
    QByteArray jsonData = jsondoc.toJson();
    udpSocket->writeDatagram(jsonData,destIp,destPort);
}

//判斷自己是不是
bool ChatWindow::checkSelfIp(const QHostAddress &ip)
{
    //判斷是否是自己在登陸發送的廣播消息
    QString hostName   = QHostInfo::localHostName();
    //使用localHostname擷取自己目前的本地IP位址,并儲存在hostName中
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    //将QHstInfo對象使用fromName函數儲存一個鍵值對
    QList<QHostAddress> addressList = hostInfo.addresses();
    //将創咋好一個QHostaddtess的元素 等于 hostInFo.addresses.
    //儲存了所有的主機位址
    for(int i = 0;i < addressList.size();i ++){
       if(addressList[i] == ip){
           return true;//周遊
       }
    }

    return false;
}

           

第八部分 将退出的好友删除利用Qlist類将我們的連結清單中判斷是否有相同的值

void ChatWindow::doUserQuit(const QHostAddress &ip, const QString &name, short port)
{
      QString text = QString("%1\n%2:%3").arg(name).arg(ip.toString()).arg(port);
      QList<QListWidgetItem *> itemList = ui->listWidget->findItems(text,Qt::MatchExactly);
      for(int i = 0;i < itemList.size();i ++){
          ui->listWidget->removeItemWidget(itemList[i]);
          delete itemList[i];
      }

      return;
}
           

第九步再将自己的發送的資訊給發出來

void ChatWindow::displaySendChatMessage(const QString &name, const QString &content)
{

    QTime time = QTime::currentTime();
    QString  timeString = time.toString("hh:mm:ss");
    QString html = QString(
                    "<br align = \"right\">"
                   "<h3 align = \"right\"><font verdana\" color=\"red\">%1 %2</font></h3>"
                    "<p  align = \"right\"><font size=\"4\" color=\"red\">&nbsp;%3</p>"

                             ).arg(name).arg(timeString).arg(content);

     ui->dis->insertHtml(html);

}
//顯示函數 将自己的名字和資料列印出來

void ChatWindow::displayRecvChatMessage(const QString &name, const QString &content)
{


    QTime time = QTime::currentTime();
    QString  timeString = time.toString("hh:mm:ss");
    QString html = QString(
                    "<br  align = \"left\">"
                   "<h3 align = \"left\"><font verdana\" color=\"red\">%1 %2</font></h3>"
                    "<p align = \"left\"><font size=\"4\" color=\"blue\">&nbsp;%3</p>"

                             ).arg(name).arg(timeString).arg(content);

     ui->dis->insertHtml(html);


}

           

第十步顯示我們的發送的json聊天語句

void ChatWindow::displaySendChatMessage(const QString &name, const QString &content)
{

    QTime time = QTime::currentTime();
    QString  timeString = time.toString("hh:mm:ss");
    QString html = QString(
                    "<br align = \"right\">"
                   "<h3 align = \"right\"><font verdana\" color=\"red\">%1 %2</font></h3>"
                    "<p  align = \"right\"><font size=\"4\" color=\"red\">&nbsp;%3</p>"

                             ).arg(name).arg(timeString).arg(content);

     ui->dis->insertHtml(html);

}
//顯示函數 将自己的名字和資料列印出來

void ChatWindow::displayRecvChatMessage(const QString &name, const QString &content)
{


    QTime time = QTime::currentTime();
    QString  timeString = time.toString("hh:mm:ss");
    QString html = QString(
                    "<br  align = \"left\">"
                   "<h3 align = \"left\"><font verdana\" color=\"red\">%1 %2</font></h3>"
                    "<p align = \"left\"><font size=\"4\" color=\"blue\">&nbsp;%3</p>"

                             ).arg(name).arg(timeString).arg(content);

     ui->dis->insertHtml(html);


}
           

如果需要完整代碼請與我聯系~QQ:1339781385

基于QT的UDP網絡聊天室(QQ界面)