C++聊天软件

本文介绍了一个聊天程序的设计与实现,包括用户界面布局、消息传递机制、文件发送功能等关键部分。程序使用Qt框架进行开发,实现了用户登录、消息发送、文件传输等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

主要代码如下:

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);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值