基于QT的局域网聊天

1.Drawer

Drawer.h

#ifndef DRAWER_H
#define DRAWER_H
#include <QToolBox>
#include <QToolButton>
#include "Widget.h"
class Drawer : public QToolBox
{
    Q_OBJECT
public:
    Drawer(QWidget *parent=0,Qt::WindowFlags f=0);

private:
    QToolButton *toolButton1;
    QToolButton *toolButton2;
    QToolButton *toolButton3;
    QToolButton *toolButton4;
    QToolButton *toolButton5;
    QToolButton *toolButton6;
    QToolButton *toolButton7;
    QToolButton *toolButton8;
    QToolButton *toolButton9;
private slots://显示聊天窗口的函数
    void showChatWidget1();
    void showChatWidget2();
    void showChatWidget3();
    void showChatWidget4();
    void showChatWidget5();
    void showChatWidget6();
    void showChatWidget7();
    void showChatWidget8();
    void showChatWidget9();
private://用户对应聊天窗口对象的指针
    Widget *chatWidget1;
    Widget *chatWidget2;
    Widget *chatWidget3;
    Widget *chatWidget4;
    Widget *chatWidget5;
    Widget *chatWidget6;
    Widget *chatWidget7;
    Widget *chatWidget8;
    Widget *chatWidget9;
};

#endif // DRAWER_H

Drawer.cpp

#include "drawer.h"
#include<QGroupBox>
#include<QVBoxLayout>
Drawer::Drawer(QWidget *parent,Qt::WindowFlags f)
    :QToolBox(parent,f)
{
    setWindowTitle(tr("The QQ Created by samson"));//主窗口标题
    setWindowIcon(QIcon(":/images/qq.png"));//设置主窗口图标
    toolButton1=new QToolButton;
    toolButton1->setText(tr("samson1"));
    toolButton1->setIcon(QPixmap(":/images/samson1.png"));
    toolButton1->setIconSize(QSize(60,60));
    toolButton1->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton1->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton1,SIGNAL(clicked()),this,SLOT(showChatWidget1()));

    toolButton2=new QToolButton;
    toolButton2->setText(tr("samson2"));
    toolButton2->setIcon(QPixmap(":/images/samson2.png"));
    toolButton2->setIconSize(QSize(60,60));
    toolButton2->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton2->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton2,SIGNAL(clicked()),this,SLOT(showChatWidget2()));

    toolButton3=new QToolButton;
    toolButton3->setText(tr("samson3"));
    toolButton3->setIcon(QPixmap(":/images/samson3.png"));
    toolButton3->setIconSize(QSize(60,60));
    toolButton3->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton3->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton3,SIGNAL(clicked()),this,SLOT(showChatWidget3()));

    toolButton4=new QToolButton;
    toolButton4->setText(tr("samson4"));
    toolButton4->setIcon(QPixmap(":/images/samson4.png"));
    toolButton4->setIconSize(QSize(60,60));
    toolButton4->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton4->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton4,SIGNAL(clicked()),this,SLOT(showChatWidget4()));

    toolButton5=new QToolButton;
    toolButton5->setText(tr("samson5"));
    toolButton5->setIcon(QPixmap(":/images/samson5.png"));
    toolButton5->setIconSize(QSize(60,60));
    toolButton5->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton5->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton5,SIGNAL(clicked()),this,SLOT(showChatWidget5()));

    toolButton6=new QToolButton;
    toolButton6->setText(tr("samson6"));
    toolButton6->setIcon(QPixmap(":/images/samson6.png"));
    toolButton6->setIconSize(QSize(60,60));
    toolButton6->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton6->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton6,SIGNAL(clicked()),this,SLOT(showChatWidget6()));

    toolButton7=new QToolButton;
    toolButton7->setText(tr("samson7"));
    toolButton7->setIcon(QPixmap(":/images/samson7.png"));
    toolButton7->setIconSize(QSize(60,60));
    toolButton7->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton7->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton7,SIGNAL(clicked()),this,SLOT(showChatWidget7()));

    toolButton8=new QToolButton;
    toolButton8->setText(tr("samson8"));
    toolButton8->setIcon(QPixmap(":/images/samson8.png"));
    toolButton8->setIconSize(QSize(60,60));
    toolButton8->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton8->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton8,SIGNAL(clicked()),this,SLOT(showChatWidget8()));

    toolButton9=new QToolButton;
    toolButton9->setText(tr("samson9"));
    toolButton9->setIcon(QPixmap(":/images/samson9.png"));
    toolButton9->setIconSize(QSize(60,60));
    toolButton9->setAutoRaise(true);//当鼠标离开时,按钮自动恢复弹起状态
    toolButton9->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);//设置按钮的文字显示在图标旁边
    connect(toolButton9,SIGNAL(clicked()),this,SLOT(showChatWidget9()));

    QGroupBox *groupBox=new QGroupBox;
    QVBoxLayout  *boxlayout=new QVBoxLayout(groupBox);
    boxlayout->setMargin(20);//布局中窗体显示间距
    boxlayout->setAlignment(Qt::AlignLeft);//布局中窗体显示位置

    boxlayout->addWidget(toolButton1);
    boxlayout->addWidget(toolButton2);
    boxlayout->addWidget(toolButton3);
    boxlayout->addWidget(toolButton4);
    boxlayout->addWidget(toolButton5);
    boxlayout->addWidget(toolButton6);
    boxlayout->addWidget(toolButton7);
    boxlayout->addWidget(toolButton8);
    boxlayout->addWidget(toolButton9);
    boxlayout->addStretch();//插入占位符

    this->addItem((QWidget *)groupBox,QStringLiteral("群成员"));
}

void Drawer::showChatWidget1()
{
    //以toolButton1文本为用户名创建一个Widget类的实例,相当于一个窗口
    chatWidget1=new Widget(0,toolButton1->text());
    chatWidget1->setWindowTitle(toolButton1->text());
    chatWidget1->setWindowIcon(toolButton1->icon());
    chatWidget1->show();
}

void Drawer::showChatWidget2()
{
    chatWidget2=new Widget(0,toolButton2->text());
    chatWidget2->setWindowTitle(toolButton2->text());
    chatWidget2->setWindowIcon(toolButton2->icon());
    chatWidget2->show();
}

void Drawer::showChatWidget3()
{
    chatWidget3=new Widget(0,toolButton3->text());
    chatWidget3->setWindowTitle(toolButton3->text());
    chatWidget3->setWindowIcon(toolButton3->icon());
    chatWidget3->show();
}

void Drawer::showChatWidget4()
{

    chatWidget4=new Widget(0,toolButton4->text());
    chatWidget4->setWindowTitle(toolButton4->text());
    chatWidget4->setWindowIcon(toolButton4->icon());
    chatWidget4->show();
}

void Drawer::showChatWidget5()
{
    chatWidget5=new Widget(0,toolButton5->text());
    chatWidget5->setWindowTitle(toolButton5->text());
    chatWidget5->setWindowIcon(toolButton5->icon());
    chatWidget5->show();
}

void Drawer::showChatWidget6()
{
    chatWidget6=new Widget(0,toolButton6->text());
    chatWidget6->setWindowTitle(toolButton6->text());
    chatWidget6->setWindowIcon(toolButton6->icon());
    chatWidget6->show();
}

void Drawer::showChatWidget7()
{
    chatWidget7=new Widget(0,toolButton7->text());
    chatWidget7->setWindowTitle(toolButton7->text());
    chatWidget7->setWindowIcon(toolButton7->icon());
    chatWidget7->show();
}

void Drawer::showChatWidget8()
{
    chatWidget8=new Widget(0,toolButton8->text());
    chatWidget8->setWindowTitle(toolButton8->text());
    chatWidget8->setWindowIcon(toolButton8->icon());
    chatWidget8->show();
}

void Drawer::showChatWidget9()
{
    chatWidget9=new Widget(0,toolButton9->text());
    chatWidget9->setWindowTitle(toolButton9->text());
    chatWidget9->setWindowIcon(toolButton9->icon());
    chatWidget9->show();
}

2.Server

Server.h

#ifndef SERVER_H
#define SERVER_H

#include <QDialog>
#include <QtGlobal>
#include <QTime>
#include <QFile>
#include<QTcpServer>
#include<QTcpSocket>
namespace Ui {
class Server;
}

class Server : public QDialog
{
    Q_OBJECT

public:
    explicit Server(QWidget *parent = 0);
    ~Server();
    void initSrv();//初始化服务器
    void refused();//关闭服务器
protected:
    void closeEvent(QCloseEvent *);
private:
    Ui::Server *ui;
    qint16 tPort;
    QTcpServer *tSrv;
    QString fileName;
    QString theFilename;
    QFile *localfile;//待发送的文件
    int payloadSize;
    qint64 totalBytes;//总共需发送的字节数
    qint64 bytesWriteen;//已发送的字节数
    qint64 bytesToBeWritten;//待发送的字节数

    QByteArray outBlock;//缓冲一次发送数据
    QTcpSocket *clntConn;//客户端连接的套接字
    QTime time;
 private slots:
    void SendMsg();//发送数据
    void UpdateProcess(qint64 numBytes);//更新进度条
    void on_sOpenBtn_clicked();

    void on_sSendBtn_clicked();

    void on_sCloseBtn_clicked();

signals:
    void sndFileName(QString fileName);
};

#endif // SERVER_H

Server.cpp

#include "server.h"
#include "ui_server.h"
#include<QTcpServer>
#include<QTcpSocket>
#include<QFile>
#include<QMessageBox>
#include <QFileDialog>
#include <QHostAddress>
Server::Server(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Server)
{
    ui->setupUi(this);
    setFixedSize(400,207);
    tPort=5555;
    tSrv=new QTcpServer(this);
    connect(tSrv,SIGNAL(newConnection()),this,SLOT(SendMsg()));
    initSrv();
}

Server::~Server()
{
    delete ui;
}
void Server::initSrv()
{
    payloadSize=64*1024;
    totalBytes=0;
    bytesWriteen=0;
    bytesToBeWritten=0;
    ui->progressBar->reset();
    ui->sOpenBtn->setEnabled(true);
    ui->sSendBtn->setEnabled(true);

    tSrv->close();//关闭服务器

}
void Server::SendMsg()
{
    ui->sSendBtn->setEnabled(false);
    clntConn=tSrv->nextPendingConnection();
    connect(clntConn,SIGNAL(bytesWritten(qint64)),this,SLOT(UpdateProcess(qint64)));
    ui->sStatusLbl->setText(tr("传送文件 %1").arg(theFilename));
    localfile=new QFile(fileName);
    if(!localfile->open(QFile::ReadOnly))//以只读方式打开文件
    {
		 QMessageBox::warning(this,tr("File"),tr("Can not open %1").arg(fileName));
		 return ;
    }
    totalBytes=localfile->size();
    QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
    time.start();//计时器开始,统计传输的时间
    QString currentFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
    sendOut<<qint64(0)<<qint64(0)<<currentFileName;
    totalBytes += outBlock.size();  //总大小为文件大小加上文件名等信息大小
    sendOut.device()->seek(0);  //回到字节流起点来写好前面连个qint64,分别为总大小和文件名等信息大小
    sendOut<<totalBytes<<qint64(outBlock.size());
    bytesToBeWritten=totalBytes-clntConn->write(outBlock);  //将读到的文件发送到套接字
    outBlock.resize(0);//清空发送缓冲区以备下次备用
}
void Server::UpdateProcess(qint64 numBytes)
{
    qApp->processEvents();//传输大文件不会冻结
    bytesWriteen+=(int)numBytes;
    if(bytesWriteen>0)
    {
        outBlock=localfile->read(qMin((int)bytesToBeWritten,payloadSize));
        bytesToBeWritten-=clntConn->write(outBlock);
        outBlock.resize(0);//清空发送缓冲区以备下次备用
    }

    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesWriteen);
    float usetime=time.elapsed();
    double speed=bytesWriteen/usetime;
    ui->sStatusLbl->setText(tr("has been sent:%1MB (%2MB/s)  all:%3MB used time:%4s\n  Estimated time remaining:%5秒" )
                            .arg(bytesWriteen/(1024*1024))
                            .arg(speed*1000/(1024*10234),0,'f',0)
                            .arg(totalBytes/(1024*1024))
                            .arg(usetime/1000,0,'f',0)
                            .arg(totalBytes/speed/1000-usetime/1000,0,'f',0));
    if(bytesWriteen==totalBytes)
        {
        localfile->close();
        localfile->close();
        ui->sStatusLbl->setText(QStringLiteral("transfer %1 成功").arg(theFilename));
    }

}

void Server::on_sOpenBtn_clicked()
{
    fileName=QFileDialog::getOpenFileName(this);
    if(!fileName.isEmpty())
    {

        theFilename=fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
        ui->sStatusLbl->setText(tr("The file to be transferred is:%1").arg(theFilename));
        ui->sOpenBtn->setEnabled(false);

    }
}

void Server::on_sSendBtn_clicked()
{
    if(!tSrv->listen(QHostAddress::Any,tPort))//监听
    {
        tSrv->close();
        return;

    }
    ui->sStatusLbl->setText(tr("Waiting for recipients to receive..."));
    sndFileName(theFilename);
}

void Server::on_sCloseBtn_clicked()
{
    if(tSrv->isListening())
    {
        tSrv->close();
        if(localfile->isOpen())
            localfile->close();
        clntConn->abort();

    }
    close();
}
void Server::closeEvent(QCloseEvent *)
{
    on_sCloseBtn_clicked();
}
void Server::refused()
{

    tSrv->close();
    ui->sStatusLbl->setText(QStringLiteral("发送完毕"));

}

3.client

client.h

#ifndef CLIENT_H
#define CLIENT_H

#include <QDialog>
#include<QTime>
#include<QFile>
#include<QHostAddress>
#include <QTcpSocket>
namespace Ui {
class client;
}

class client : public QDialog
{
    Q_OBJECT

public:
    explicit client(QWidget *parent = 0);
    ~client();
    void setHostAddr(QHostAddress addr);//获取发送端IP地址
    void setFileName(QString name);//获取文件路径
protected:
    void closeEvent(QCloseEvent *event);
private:
    QTcpSocket *tClnt;//客户端套接字
    quint16 blockSize;
    QHostAddress hostAddr;
    qint16 port;//端口
    qint64 totalBytes;//总共需要接收的字节
    qint64 byteReceived;//已经接收到的字节数
    qint64 filenamesize;
    QString filename;
    QFile *locFile;
    QByteArray inBlock;
    QTime time;
private slots:
    void newConn();//连接到服务器
    void readMsg();//读取文件数据
    void DisplayErr(QAbstractSocket::SocketError);//显示错误信息
    void on_CCancleBtn_clicked();
    void on_cCloseBtn_clicked();

private:
    Ui::client *ui;
};

#endif // CLIENT_H

client.cpp

#include "client.h"
#include "ui_client.h"
#include<QDebug>
#include <QMessageBox>
client::client(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::client)
{
    ui->setupUi(this);
    setFixedSize(400,190);
    port=5555;
    totalBytes=0;
    byteReceived=0;
    filenamesize=0;
    tClnt=new QTcpSocket;
    connect(tClnt,SIGNAL(readyRead()),this,SLOT(readMsg()));
    connect(tClnt,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(DisplayErr(QAbstractSocket::SocketError)));
}

client::~client()
{
    delete ui;
}
void client::DisplayErr(QAbstractSocket::SocketError sockErr)
{

    switch(sockErr)
    {
        case QAbstractSocket::RemoteHostClosedError:
            break;
    default:
        qDebug()<<tClnt->errorString();
    }

}
void client::newConn()
{
    //设置与服务器的连接
    blockSize=0;
    tClnt->abort();
    tClnt->connectToHost(hostAddr,port);
    time.start();
}
void client::readMsg()
{
    QDataStream in(tClnt);
    float useTime=time.elapsed();
    if(byteReceived<=sizeof(qint64)*2)//控制每次接收到的大小
    {
        if((tClnt->bytesAvailable()>=sizeof(qint64)*2) && (filenamesize==0))
        {
            in>>totalBytes>>filenamesize;
            byteReceived+=sizeof(qint64)*2;
        }
        if((tClnt->bytesAvailable()>=filenamesize)&&(filenamesize!=0))
        {
            in>>filename;
            byteReceived+=filenamesize;
            if(!locFile->open(QFile::WriteOnly))
            {
                QMessageBox::warning(this,tr("App"),tr("Can not open file%1").arg(filename));
                return ;
            }
        }else
        {

            return ;
        }
    }
    if(byteReceived<totalBytes)
    {
        byteReceived+=tClnt->bytesAvailable();
        inBlock=tClnt->readAll();
        locFile->write(inBlock);
        inBlock.reserve(0);


    }
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(byteReceived);
    double speed=byteReceived/useTime;
    ui->cStatusLbl->setText(tr("Already received:%1MB (%2MB/s) \n Total%3MB Used Time:%4 Lefted Time:%5")
                            .arg(byteReceived/(1024*1024))
                            .arg(speed*1000/(1024*1024),0,'f',2)
                            .arg(useTime/1000,0,'f',0)
                            .arg(totalBytes/speed/1000-useTime/1000,0,'f',0));
    if(byteReceived==totalBytes)
    {

        locFile->close();
        tClnt->close();
        ui->cStatusLbl->setText(tr("Received file :%1").arg(filename));
    }
}

void client::on_CCancleBtn_clicked()
{
    tClnt->abort();
    if(locFile->isOpen())
        locFile->close();
}

void client::on_cCloseBtn_clicked()
{
    tClnt->abort();
    if(locFile->isOpen())
        locFile->close();
    close();
}
void client::closeEvent(QCloseEvent *event)
{
    on_cCloseBtn_clicked();
}
void client::setHostAddr(QHostAddress addr)
{
    hostAddr=addr;
    newConn();
}

void client::setFileName(QString name)
{
   locFile=new QFile(name);

}

4.Widget

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QUdpSocket>
#include <QIODevice>
#include <QMessageBox>
#include <QAbstractScrollArea>
#include <QNetworkInterface>
#include <QDateTime>
#include<QHostAddress>
#include"server.h"
#include"client.h"
namespace Ui {
class Widget;
}
//定义(聊天信息,新用户加入,用户退出,文件名,拒绝接收文件),区分消息类型
enum MsgType{Msg,UsrEnter,UsrLeft,FileName,Refuse};
class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0,QString str = 0);
    ~Widget();
protected:
    //处理新用户加入
    void MyusrEnter(QString usrname,QString ipaddr);
    //处理用户离开
    void MyusrLeft(QString usrname,QString time);
    //广播UDP消息
    void sendMsg(MsgType type,QString srvaddr="");
    //获取IP地址
    QString getIP();
    //获取用户名
    QString getUsr();
    //获取聊天信息
    QString getMsg();

protected:
    //判断是否接收该文件
    void hasPendingFile(QString usrname,QString srcvaddr,QString clntaddr,QString Filename);

private:
    Ui::Widget *ui;
    QUdpSocket *udpSocket;
    qint16 port;
    QString uName;
    QString Filename;
    Server *src;
    QColor color;
private slots:
    void RecvUdpMsg();//接收信息
    void MyPushSend();//按下发送按钮
    void MyPushExit();//按下退出按钮
    void GetFileName(QString);
    void on_sendTBtn_clicked();
    void on_fontCbx_currentFontChanged(const QFont &f);

    void on_sizecbx_currentTextChanged(const QString &arg1);
    void on_colorTBtn_clicked();
    void on_boldTBtn_clicked(bool checked);
    void on_italicTBtn_clicked(bool checked);
    void on_underlineTBtn_clicked(bool checked);
    void on_SaveTBtn_clicked();
    void on_clearTBtn_clicked();
    void on_exitBtn_clicked();
};

#endif // WIDGET_H

Widget.cpp

#include<QDebug>
#include<QScrollBar>
#include<QFileDialog>
#include<QMessageBox>
#include<QColorDialog>
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent, QString str) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    uName=str;
    udpSocket=new QUdpSocket;
    port=23232;
    udpSocket->bind(port,QAbstractSocket::ShareAddress|QAbstractSocket::ReuseAddressHint);
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(RecvUdpMsg()));
    connect(ui->sendBtn,SIGNAL(clicked()),this,SLOT(MyPushSend()));
    connect(ui->exitBtn,SIGNAL(clicked()),this,SLOT(MyPushExit()));
    connect(ui->boldTBtn,SIGNAL(clicked()),this,SLOT(setFontWeight(bool)));
    sendMsg(UsrEnter);

    src=new Server(this);
    connect(src,SIGNAL(sndFileName(QString)),this,SLOT(GetFileName(QString)));

}

Widget::~Widget()
{
    delete ui;
}

void Widget::sendMsg(MsgType type,QString srvaddr)
{
    QByteArray data;
    QDataStream out(&data,QIODevice::WriteOnly);
    QString address=getIP();
    out<<type<<getUsr();
    switch(type)
    {
    case Msg:
    {
        if(ui->msgTxtEdit->toPlainText()==NULL)
        {
            QMessageBox::warning(0,tr("warning"),tr("File is empty"),QMessageBox::Ok);
            return;
        }
        out<<address<<getMsg();
        ui->msgBrowser->verticalScrollBar()->setValue(ui->msgBrowser->verticalScrollBar()->maximum());
        break;
    }
    case UsrEnter:
        out<<address;
    case UsrLeft:
        break;
    case FileName:
        {
            int row=ui->usrTblWidget->currentRow();
            QString clntaddr=ui->usrTblWidget->item(row,1)->text();
            out<<address<<clntaddr<<Filename;
            break;
        }
    case Refuse:
        {
            out<<address;
            break;
        }
    }
    udpSocket->writeDatagram(data,data.length(),QHostAddress::Broadcast,port);
}
void Widget::MyPushSend()
{
    sendMsg(Msg);

}
void Widget::MyPushExit()
 {
     sendMsg(UsrLeft);
 }

void Widget::RecvUdpMsg()
{
    if(udpSocket->hasPendingDatagrams())//有可读数据
        {

        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());
        QDataStream in(&datagram,QIODevice::ReadOnly);
        int msgType;
        in>>msgType;
        QString usrName,ipAddr,msg;
        QString time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm::ss");
        QFont font;
        font.setFamily("Times New Roman");
        font.setPointSize(12);
        switch(msgType)
        {
            case Msg:
                {
                    in>>usrName>>ipAddr>>msg;
                    qDebug()<<msg;
                    ui->msgBrowser->setTextColor(Qt::blue);
                    ui->msgBrowser->setCurrentFont(font);
                    ui->msgBrowser->append("["+usrName+"]"+time);
                    ui->msgBrowser->append(msg);
                    break;
                  }
            case UsrEnter:
                {
                    in>>usrName>>ipAddr;
                    MyusrEnter(usrName,ipAddr);
                    break;
                }
            case UsrLeft:
                {
                    in>>usrName;
                    MyusrLeft(usrName,time);
                 break;
                }
            case FileName:
                {
                    in>>usrName>>ipAddr;
                    QString clntAddr,fileName;
                    in>>clntAddr>>fileName;
                    hasPendingFile(usrName,ipAddr,clntAddr,fileName);
                    break;
                }
            case Refuse:
                {
                    in>>usrName;
                    QString srvAddr;
                    in>>srvAddr;
                    QString ipAddr=getIP();
                    if(ipAddr==srvAddr)
                    {
                        src->refused();
                    }
                    break;
                }
        }
    }



}
 void Widget::hasPendingFile(QString usrname,QString srcvaddr,QString clntaddr,QString Filename)
 {

     QString ipAddr=getIP();
     if(ipAddr==clntaddr)
     {

         int btn=QMessageBox::information(this,QObject::tr("Recv File"),QObject::tr("from %1 (%2) %3 ").arg(usrname).arg(srcvaddr).arg(Filename),QMessageBox::Ok,QMessageBox::No);
		 if (btn == QMessageBox::Ok)
         {
             QString name=QFileDialog::getSaveFileName(0,tr("save The file"),Filename);
             if(!name.isEmpty())
             {
                 client *clnt=new client;
                 clnt->setFileName(name);
                 clnt->setHostAddr(QHostAddress(srcvaddr));
                 clnt->show();
             }
         }else
         {
             sendMsg(Refuse,srcvaddr);
         }
     }
 }

//处理新用户加入
void Widget::MyusrEnter(QString usrname,QString ipaddr)
{
    bool isEmpty=ui->usrTblWidget->findItems(usrname,Qt::MatchExactly).isEmpty();
    if(isEmpty)//没有这个用户则在右侧加入这个用户
    {
        QTableWidgetItem *usr=new QTableWidgetItem(usrname);
        QTableWidgetItem *ip=new QTableWidgetItem(ipaddr);
        ui->usrTblWidget->insertRow(0);
        ui->usrTblWidget->setItem(0,0,usr);
        ui->usrTblWidget->setItem(0,1,ip);
        ui->msgBrowser->setTextColor(Qt::gray);
        ui->msgBrowser->setCurrentFont(QFont(("Times New Roman"),10));
        ui->msgBrowser->append(QStringLiteral("%1在线").arg(usrname));
        ui->usrNumLbl->setText(QStringLiteral("在线人数%1").arg(ui->usrTblWidget->rowCount()));
        sendMsg(UsrEnter);
    }
}

//处理用户离开
void Widget::MyusrLeft(QString usrname,QString time)
{
    int rowNum=ui->usrTblWidget->findItems(usrname,Qt::MatchExactly).first()->row();
    ui->usrTblWidget->removeRow(rowNum);
    ui->msgBrowser->setTextColor(Qt::gray);
    ui->msgBrowser->setCurrentFont(QFont(("Times New Roman"),10));
    ui->msgBrowser->append(QStringLiteral("%1在%2下线").arg(usrname).arg(time));
    ui->usrNumLbl->setText(QStringLiteral("在线人数%1").arg(ui->usrTblWidget->rowCount()));
    ui->usrNumLbl->setText(QStringLiteral("在线人数%1").arg(ui->usrTblWidget->rowCount()));
    sendMsg(UsrEnter);
}

//获取IP地址
QString Widget::getIP()
{
    QString strIpAddress;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    // 获取第一个本主机的IPv4地址
    int nListSize = ipAddressesList.size();
    for (int i = 0; i < nListSize; ++i)
    {
           if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
               ipAddressesList.at(i).toIPv4Address()) {
               strIpAddress = ipAddressesList.at(i).toString();
               break;
           }
     }
     // 如果没有找到,则以本地IP地址为IP
     if (strIpAddress.isEmpty())
        strIpAddress = QHostAddress(QHostAddress::LocalHost).toString();
     return strIpAddress;

}

//获取用户名
QString Widget::getUsr()
{
    return uName;
}

//获取聊天信息
QString Widget::getMsg()
{

    QString msg=ui->msgTxtEdit->toHtml();
    ui->msgTxtEdit->clear();
    ui->msgTxtEdit->setFocus();//设置焦点
    return msg;
}


void Widget::GetFileName(QString name)
{
    Filename=name;
    sendMsg(FileName);

}

void Widget::on_sendTBtn_clicked()
{
    if(ui->usrTblWidget->selectedItems().isEmpty())
    {
        QMessageBox::warning(0,tr("Please Choose people"),tr("Select the target user"),QMessageBox::Ok);
        return;

    }
    src->show();
    src->initSrv();
}

void Widget::on_fontCbx_currentFontChanged(const QFont &f)
{
    ui->msgTxtEdit->setCurrentFont(f);
    ui->msgTxtEdit->setFocus();//焦点转移到文本框区域
}



void Widget::on_sizecbx_currentTextChanged(const QString &arg1)
{
    ui->msgTxtEdit->setFontPointSize(arg1.toDouble());
    ui->msgTxtEdit->setFocus();
}

void Widget::on_colorTBtn_clicked()
{
    color=QColorDialog::getColor(color,this);
    ui->msgTxtEdit->setTextColor(color);
    ui->msgTxtEdit->setFocus();
}
void Widget::on_boldTBtn_clicked(bool checked)
{
    if(checked)
    {

        ui->msgTxtEdit->setFontWeight(QFont::Bold);
    }else
    {
        ui->msgTxtEdit->setFontWeight(QFont::Normal);
    }
    ui->msgTxtEdit->setFocus();
}
void Widget::on_italicTBtn_clicked(bool checked)
{
    ui->msgTxtEdit->setFontItalic(checked);
    ui->msgTxtEdit->setFocus();
}

void Widget::on_underlineTBtn_clicked(bool checked)
{
    ui->msgTxtEdit->setFontUnderline(checked);
    ui->msgTxtEdit->setFocus();
}

void Widget::on_SaveTBtn_clicked()
{
    if(ui->msgBrowser->document()->isEmpty())
        QMessageBox::warning(0,tr("warning"),tr("Chat history is empty and can't be saved"),QMessageBox::Ok);
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                 "./Save.txt",
                                 tr(" (*.txt)"));
    QFile file(fileName);
    if(file.open(QIODevice::Text|QIODevice::WriteOnly))
    {

        QTextStream my_Stream(&file);
        my_Stream<<ui->msgBrowser->toPlainText();
    }
}

void Widget::on_clearTBtn_clicked()
{
    ui->msgBrowser->clear();
}

void Widget::on_exitBtn_clicked()
{
    close();
}

5.main

mian.h

#include "widget.h"
#include <QApplication>
#include <drawer.h>
#include <Qt>
#include<QDebug>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //Widget w;
   // w.show();
    Drawer drawer;
    drawer.resize(250,700);
    /*
    drawer.setAutoFillBackground(true);
   QPalette palette;
   QPixmap pixmap(":/images/back.jpg");
   palette.setBrush(QPalette::Window, QBrush(pixmap));
   drawersetPalette(palette);

*/


    drawer.setStyleSheet("background-image: url(:/images/backNew2.jpg);");
    drawer.show();

    return a.exec();
}


猜你喜欢

转载自blog.csdn.net/qq_35703848/article/details/79805960