C++聊天软件

1 篇文章 0 订阅

群聊
这里写图片描述
这里写图片描述

主要代码如下:

MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
    ui.setupUi(this);
    QStringList qList;
    qList << "15" << "16" << "17" << "18" << "19" << "20" << "21"\
        << "22" << "23" << "24";
    ui.comboBox->addItems(qList);
    ui.numberLabel->setAlignment(Qt::AlignCenter);
    qList.clear();
    qList << tr("用户名") << tr("IP地址");
    ui.tableWidget->setColumnCount(2);
    ui.tableWidget->setHorizontalHeaderLabels (qList);
    ui.tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    connect(ui.textEdit,SIGNAL(currentCharFormatChanged(const QTextCharFormat&)),\
        this,SLOT(on_currentCharFormatChanged(const QTextCharFormat&)));
    connect(ui.tableWidget,SIGNAL(doubleClicked (const QModelIndex & )),\
        this,SLOT(on_doubleClicked(const QModelIndex &)));

    this->setWindowTitle(tr("聊天程序"));
    port = 20000;
    hostName = QHostInfo::localHostName();
    address = getIP();

    chatUSocket = new QUdpSocket(this);
    chatUSocket->bind(port,QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
    connect(chatUSocket,SIGNAL(readyRead()),this,SLOT(processMessage()));

    sendFileDlg = new SendFileDlg(this);
    connect(sendFileDlg,SIGNAL(sendFile(const STU_FILE&)),this,SLOT(getFile(const STU_FILE&)));

    STU_HEADER heard = {MainWindow::LOGIN,hostName,address};
    sendMessage(Message(heard));
    qDebug() << "Date:" << QDate::currentDate();
}

MainWindow::~MainWindow()
{
    chatUSocket->close();
    delete chatUSocket;
    delete sendFileDlg;
}

void MainWindow::on_fontComboBox_currentFontChanged( const QFont & font )
{
    ui.textEdit->setCurrentFont(font);
    ui.textEdit->setFocus();
}

void MainWindow::on_comboBox_currentIndexChanged ( const QString arg )
{
    ui.textEdit->setFontPointSize(arg.toDouble());
    ui.textEdit->setFocus();
}

void MainWindow::on_boldToolBtn_clicked( bool checked )
{
    if(checked)
        ui.textEdit->setFontWeight(QFont::Bold);
    else
        ui.textEdit->setFontWeight(QFont::Normal);
    ui.textEdit->setFocus();
}

void MainWindow::on_italicToolBtn_clicked( bool checked )
{
    ui.textEdit->setFontItalic(false);
    ui.textEdit->setFocus();
}

void MainWindow::on_underlineToolBtn_clicked( bool checked )
{
    ui.textEdit->setFontUnderline(checked);
    ui.textEdit->setFocus();
}

void MainWindow::on_colorToolBtn_clicked()
{
    QColorDialog *colorDlg = new QColorDialog(this);
    colorDlg->open();
    connect(colorDlg,SIGNAL(colorSelected(const QColor&)),this,SLOT(on_colorSelected(const QColor&)));
}

void MainWindow::on_sendToolBtn_clicked()
{
    int row = ui.tableWidget->currentRow();
    if (row == -1)
    {
        QMessageBox::warning(this,tr("提示"),tr("请选则发送用户"),QMessageBox::Ok);
        return;
    }
    sendFileDlg->show();
    sendFileDlg->init();
}

void MainWindow::on_saveToolBtn_clicked()
{

}

void MainWindow::on_clearToolBtn_clicked()
{
    ui.textBrowser->clear();
}

void MainWindow::on_sendPushBtn_clicked()
{
    QString msg;
    msg = ui.textEdit->toPlainText();
    if ("" == msg)
    {
        QMessageBox::warning(this,tr("警告"),tr("发送内容不能为空"),QMessageBox::Ok);
        return;
    }
    STU_HEADER heard = {MainWindow::MESSAGE,hostName,address};
    STU_MSG stMsg = {1,msg};
    sendMessage(Message(heard,stMsg));
    ui.textEdit->clear();
}

void MainWindow::on_exitPushBtn_clicked()
{
    STU_HEADER heard = {MainWindow::LEAVE,hostName,address};
    sendMessage(Message(heard));
    close();
}

void MainWindow::processMessage()
{
    if (chatUSocket->hasPendingDatagrams())
    {
        QByteArray dataGram;
        dataGram.resize(chatUSocket->pendingDatagramSize());
        QDataStream in(&dataGram,QIODevice::ReadOnly);
        chatUSocket->readDatagram(dataGram.data(),dataGram.size());
        Message msg;
        in >> msg;
        switch (msg.heard.msgType)
        {
        case LOGIN:
            on_login(msg);
            break;
        case LEAVE:
            on_leave(msg);
            break;
        case MESSAGE:
            on_message(msg);
            break;
        case FILENAME:
            on_file(msg);
            break;
        case REFUSE:
            on_refuse(msg);
            break;
        default:
            break;
        }
    }
}

void MainWindow::sendMessage(Message& msg)
{
    QByteArray dataGram;
    QDataStream out(&dataGram,QIODevice::WriteOnly);
    out << msg;
    chatUSocket->writeDatagram(dataGram,QHostAddress::Broadcast,port);
}

void MainWindow::on_login(Message& msg)
{
    qDebug() << tr("处理登入消息");
    bool bEmpty = ui.tableWidget->findItems(msg.heard.sndHosName,Qt::MatchExactly).isEmpty();
    if (bEmpty)
    {
        QTableWidgetItem* hsNaItem = new QTableWidgetItem(msg.heard.sndHosName);
        QTableWidgetItem* addrItem = new QTableWidgetItem(msg.heard.sndAddr);
        ui.tableWidget->insertRow(0);
        ui.tableWidget->setItem(0,0,hsNaItem);
        ui.tableWidget->setItem(0,1,addrItem);
    }
    int lineNum = ui.tableWidget->rowCount();
    ui.numberLabel->setText(tr("在线人数:%1").arg(lineNum));
}

void MainWindow::on_leave(Message& msg)
{
    qDebug() << tr("处理退出消息");
    QList<QTableWidgetItem*> listItem = ui.tableWidget->findItems(msg.heard.sndHosName,Qt::MatchExactly);
    foreach(QTableWidgetItem* item,listItem)
    {
        int row = item->row();
        ui.tableWidget->removeRow(row);
    }
    int lineNum = ui.tableWidget->rowCount();
    ui.numberLabel->setText(tr("在线人数:%1").arg(lineNum));
}

const QString MainWindow::getIP()
{
    QList<QHostAddress> addrList =  QNetworkInterface::allAddresses ();
    foreach(QHostAddress addr,addrList){
        if (addr.protocol() == QAbstractSocket::IPv4Protocol)
            return addr.toString();
    }
    return NULL;
}

void MainWindow::on_message(Message& msg)
{
    if (1 == msg.msg.type)
    {
        ui.textBrowser->setTextColor(Qt::blue);
        ui.textBrowser->append("[" + msg.heard.sndHosName + "]");
        ui.textBrowser->append(msg.msg.content);
    }
    if (0 == msg.msg.type && msg.heard.recAddr==address)
    {
        if (!oneChatDlgList.contains(locOneChatDlg) || !chatList.contains(msg.heard.sndAddr))
        {
            chatList.append(msg.heard.sndAddr);
            locOneChatDlg = new OneChatDlg(this);
            oneChatDlgList.append(locOneChatDlg);
            connect(locOneChatDlg,SIGNAL(sndMsgToMainWnd(const QString&)),this,SLOT(getOneChatMsg(const QString&)));
            connect(locOneChatDlg,SIGNAL(closeWindow(OneChatDlg*)),this,SLOT(delOneChatDlg(OneChatDlg*)));
            locOneChatDlg->setModal(false);
            locOneChatDlg->show();
            locOneChatDlg->setWindowTitle(msg.heard.sndAddr);
            QList<QTableWidgetItem*> qList = ui.tableWidget->findItems(msg.heard.sndAddr,Qt::MatchExactly);
            if(qList.size() > 0)
                ui.tableWidget->setCurrentCell(qList.at(0)->row(),qList.at(0)->column());
        }
        locOneChatDlg->setWindowTitle(msg.heard.sndHosName);
        locOneChatDlg->textBro()->append("[" + msg.heard.sndHosName + "]");
        locOneChatDlg->textBro()->append(msg.msg.content);
    }
}

void MainWindow::on_colorSelected( const QColor& color)
{
    ui.textEdit->setTextColor(color);
    ui.textEdit->setFocus();
}

void MainWindow::on_file(Message& msg)
{
    qDebug() << tr("处理文件信息");
    if (msg.heard.recAddr == getIP())
    {
        int iResult =  QMessageBox::question(this,tr("提示"),\
            tr("是否接收来自:%1的文件:%2?").arg(msg.heard.sndHosName).arg(msg.file.name),\
            QMessageBox::Ok|QMessageBox::Cancel);
        if (iResult == QMessageBox::Ok)
        {
            ReceiveFileDlg *rcvFileDlg = new ReceiveFileDlg(this);
            rcvFileDlg->show();
            rcvFileDlg->setMsg(msg);
        }
        else
        {
            STU_HEADER heard = {MainWindow::REFUSE,hostName,address,msg.heard.sndHosName,\
                msg.heard.sndAddr};
            sendMessage(Message(heard));
        }
    }
}

void MainWindow::on_refuse(Message& msg)
{
    if (msg.heard.recAddr == getIP())
    {
        QMessageBox::information(this,tr("提示"),tr("%1拒绝接收你的文件").arg(msg.heard.sndHosName),\
            QMessageBox::Ok);
    }
}

void MainWindow::getFile( const STU_FILE& stFile)
{
    QString recHsname,recAddr;
    QTableWidgetItem *item;
    int row = ui.tableWidget->currentRow();
    item = ui.tableWidget->item(row,0);
    recHsname = item->text();
    item = ui.tableWidget->item(row,1);
    recAddr = item->text();
    STU_HEADER heard = {MainWindow::FILENAME,hostName,address,\
        recHsname,recAddr};
    sendMessage(Message(heard,stFile));
}

void MainWindow::on_currentCharFormatChanged( const QTextCharFormat& f)
{
    ui.textBrowser->setFont(f.font());
}

void MainWindow::on_doubleClicked( const QModelIndex & index)
{
    QString recHsname;
    QTableWidgetItem *item;
    int row = ui.tableWidget->currentRow();
    item = ui.tableWidget->item(row,0);
    recHsname = item->text();
    OneChatDlg *oneChatdlg = new OneChatDlg(this);
    connect(oneChatdlg,SIGNAL(sndMsgToMainWnd(const QString&)),this,SLOT(getOneChatMsg(const QString&)));
    connect(oneChatdlg,SIGNAL(closeWindow(OneChatDlg*)),this,SLOT(delOneChatDlg(OneChatDlg*)));
    oneChatdlg->setModal(false);
    oneChatdlg->show();
    oneChatdlg->setWindowTitle(recHsname);
    oneChatDlgList.append(oneChatdlg);
}

void MainWindow::getOneChatMsg(const QString& msg)
{
    QString recHsname,recAddr;
    QTableWidgetItem *item;
    int row = ui.tableWidget->currentRow();
    item = ui.tableWidget->item(row,0);
    recHsname = item->text();
    item = ui.tableWidget->item(row,1);
    recAddr = item->text();
    STU_HEADER heard = {MainWindow::MESSAGE,hostName,address,recHsname,recAddr};
    STU_MSG stMsg = {0,msg};
    sendMessage(Message(heard,stMsg));
}

void MainWindow::delOneChatDlg(OneChatDlg* dlg)
{
    QString title = dlg->windowTitle();
    oneChatDlgList.removeOne(dlg);
    if(chatList.contains(title))
        chatList.removeOne(title);
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
此项目为络编程的课程设计选题。目标是在 VS 下,使用 Win32 网络编程和 MFC 框架实现多人在线聊天的服务器端和客户端。用户能够选择网络中的聊天对象,通过 UDP 广播或者通过 TCP 对指定用户进行通信,方便用户的交流。最终,在 windows 操作系统下实现多人在线即时聊天功能。 服务器端功能需求 服务器能够选择端口号并且启动服务器端的 TCP 服务,等待客户端的 Socket 连接。 服务器能够接受多个客户端的请求,并且能够识别不同的客户端。为每个客户端建立唯一的身份表示。 连接成功后,服务器能接收客户端发过来的文本信息并显示。 服务器能够选择用户,并通过界面信息框发送消息。 服务器能够清空消息缓冲区域的内容。 服务器能够选择端口号并启动服务器端的 UDP 服务,并且等待客户端的数据包,接受数据并且显示。 服务器端能够显示本机的地址和状态。 客户端功能需求 某用户刚登录服务器时,服务器需对其发送实时在线用户列表。 用户可以通过指定主机地址和端口号连接指定的服务器。用户在连接过程中可以选择 TCP 或者 UDP 协议进行连接。 某用户登录或退出程序时都需要给服务器发送一个消息以通知其他用户。 用户能够通过界面发送消息。 用户界面能够显示历史消息,包括其他用户传递的消息和用户自身发送的消息。用户能够通过界面清空历史消息缓冲区 状态栏能够显示用户当前连接的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值