QT 网络聊天室设计实验报告

一、实验目的与要求
(1)了解QT Network模块基本知识
(2)掌握网络访问接口的方法
(3)熟悉获取网络接口信息的方法

二、实验内容与安排方式
(1)了解QT Network模块基本知识
(2)掌握网络访问接口的方法
(3)熟悉获取网络接口信息的方法
三、实验操作要点
1.准备工作
新建项目(ChattingRoom),并连接Qt network库。
在ChattingRoom.pro文件添加代码:QT += network:

定义一个枚举变量MessageType,用来区分不同的广播类型,其取值有Message、NewParticipant、ParticipantLife、FileName、Refuse:

定义QUdoSocket变量udpSocket:

定义私有变量port用于储存UDP使用端口:

定义函数sendMessage,用于发送用户的各种UDP数据

定义槽processPendingDatagrams,用于接收UDP广播发送来的数据

定义函数getIP、getUsername、getMessage,分别用于获取用户IP地址、用户名、用户发送信息

创建UDP套接字并进行初始化

2.聊天功能
1)用户登录
实现用户登录函数newParticipant

UDP上传登录信息

接收UDP用户登录信息

2)聊天信息
创建“发送”按钮点击信号槽发送信息

UDP发送聊天信息

接收UDP聊天信息

3)用户下线
实现用户下线函数participantLife

接收UDP用户下线信息

3.文件传送
1)TCP服务器
创建Qt设计师界面类TcpServer,并设计界面:

定义变量thsFileName,用于储存文件名:

定义变量fileName,用于储存文件路径:

定义QFile变量:

定义变量payloadSize,用于储存有效载荷大小:

定义变量TotalBytes,用于储存传送文件总大小:

定义变量byteWritten,用于储存已传送文件大小:

定义变量bytesToWrite,用于存储待传送文件大小:

定义变量tcpPort,用于设置TCP协议使用端口

定义QTcpServer变量tcpServer:

创建initServer函数用于初始化TCP服务器,设置有效载荷、文件大小等变量的初始值,以及界面信息等。

在TcpServer构造函数创建并初始化服务器

创建sendMessage函数,用于发起文件传送请求

设置“打开”按钮单击信号槽,获取待发送文件信息。设置相关变量的值。

设置“发送”按钮单击信号槽,按下“发送”按钮将服务器设置为监听状态,发送sendFileName信号,在主界面类中关联该信号并使用UDP广播将文件名发送给接收端:

在主界面类中:

设置“关闭”按钮单击信号槽,先关闭服务器,然后关闭文件发送对话框。

修改主界面函数processPendingDatagrams,并在服务器类添加函数refused,当接收端拒绝接收该文件时,便关闭服务器:

添加关闭事件处理函数,调用“关闭”按钮信号槽,关闭服务器:

添加函数updateClientProgress,用于更新文件传送对话框中的进度条

2)TCP客户端
创建Qt设计师界面类TcpClient,并设计界面:

定义QTcpSocket变量tcpClient

定义变量blockSize,用于设置传送块大小

定义QHostAddress变量hostAddress,用存储发送端IP地址:

定义变量tcpPort,用于存储TCP传输的端口:

定义变量inBlock,用于存储当前传输块:

定义变量time,用于存储传送已用时间:

以下变量同服务器类相似:

添加函数newConnect,用于创建TCP连接,开始计时:

添加函数setHostAddress,用于设置发送端的IP地址,并调用newConnect函数通过TCP建立连接:

添加函数setFileName,用于设置待接收的文件对象:

修改主界面类processPendingDatagrams函数:

添加函数hasPendingFile,用于显示客户端接收对话框:

修改主界面类sendMessage函数,拒绝接受时通过UDP上传信息:

在构造函数添加代码

添加函数readMessage,用于文件接收存储:

在构造函数添加代码:

添加函数displayError,用于传送错误处理:

设置“取消”按钮信号槽

设置“关闭”按钮信号槽:

添加关闭时间处理函数

4.其他功能
1)富文本处理
聊天信息字体选择

聊天信息字体大小选择

聊天信息字体粗体设置

聊天信息字体斜体设置

聊天信息字体下划线设置

聊天信息字体颜色设置

2)聊天记录管理
保存聊天记录

清空聊天记录

3)退出程序

软件发布
1.设置应用程序icon图标

2.生成Qt发布版应用程序

3.为应用程序添加依赖文件
另新建文件夹CRoom,将发布版文件夹中可执行文件移动过来。

打开

打开当前目录

输入命令: windeployqt ChattingRoom.exe

添加依赖文件成功

运行结果截屏
1.运行程序

2.聊天信息发送

3.文字变换

4.文件发送功能
1111

选择待传送文件

选择完成,点击发送提交传输请求

接收端收到请求

接收端同意接收文件,选择文件路径、设置文件名保存

接收端拒绝接收文件,发送端收到回执:

5.聊天记录管理
聊天记录保存

聊天记录清空

四、实验设计过程记录
选择一个聊天应用的图标作为不规则登录界面登陆该界面,主界面以图标显示聊天室,网聊天工具图标,界面进行美化或变换肤色、文件传输等。图标增加冒泡提示,鼠标移到登录图标时冒泡提示如下:点按左键可以拖移,双击左键登录,点击右键退出。
若有可能,请增加创意与特色功能如:录音,拍照、短视频上传,或实时聊天对讲或直播等。
设计过程如下:
新建项目,名称为chat,类名为widget

新建文件,Qt 》》 Qt 设计师界面类,界面模板选择Dialog without Buttons,类名为TcpClient

进入设计模式,在tcpcient.ui界面中添加控件

在tcpcient.h文件中添加代码
添加头文件
#include
#include
#include
#include
添加函数,私有变量
void setHostAddress(QHostAddress address);
void setFileName(QString fileName);

protected:
void closeEvent(QCloseEvent *);

private:
Ui::TcpClient *ui;

QTcpSocket *tcpClient;
quint16 blockSize;
QHostAddress hostAddress;
qint16 tcpPort;

qint64 TotalBytes;
qint64 bytesReceived;
qint64 bytesToReceive;
qint64 fileNameSize;
QString fileName;
QFile *localFile;
QByteArray inBlock;

QTime time;

private slots:
void on_tcpClientCancleBtn_clicked();
void on_tcpClientCloseBtn_clicked();

void newConnect();
void readMessage();
void displayError(QAbstractSocket::SocketError);

在tcpcient.cpp文件中添加代码。
添加头文件
#include
#include
#include

在构造函数中添加代码
TotalBytes = 0;
bytesReceived = 0;
fileNameSize = 0;

tcpClient = new QTcpSocket(this);
tcpPort = 6666;
connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readMessage()));
connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), this,
        SLOT(displayError(QAbstractSocket::SocketError)));

添加声明函数的代码
/ 设置文件名
void TcpClient::setFileName(QString fileName)
{
localFile = new QFile(fileName);
}

// 设置地址
void TcpClient::setHostAddress(QHostAddress address)
{
hostAddress = address;
newConnect();
}

// 创建新连接
void TcpClient::newConnect()
{
blockSize = 0;
tcpClient->abort();
tcpClient->connectToHost(hostAddress, tcpPort);
time.start();
}

// 读取数据
void TcpClient::readMessage()
{
QDataStream in(tcpClient);
in.setVersion(QDataStream::Qt_4_7);

float useTime = time.elapsed();

if (bytesReceived <= sizeof(qint64)*2) {
    if ((tcpClient->bytesAvailable()
         >= sizeof(qint64)*2) && (fileNameSize == 0))
    {
        in>>TotalBytes>>fileNameSize;
        bytesReceived += sizeof(qint64)*2;
    }
    if((tcpClient->bytesAvailable() >= fileNameSize) && (fileNameSize != 0)){
        in>>fileName;
        bytesReceived +=fileNameSize;

        if(!localFile->open(QFile::WriteOnly)){
            QMessageBox::warning(this,tr(""),tr("%1:\n%2.")
                                 .arg(fileName).arg(localFile->errorString()));
            return;
        }
    } else {
        return;
    }
}
if (bytesReceived < TotalBytes) {
    bytesReceived += tcpClient->bytesAvailable();
    inBlock = tcpClient->readAll();
    localFile->write(inBlock);
    inBlock.resize(0);
}
ui->progressBar->setMaximum(TotalBytes);
ui->progressBar->setValue(bytesReceived);

double speed = bytesReceived / useTime;
ui->tcpClientStatusLabel->setText(tr(") "
                                     "\n%3MB %4秒\n估 %5秒")
                                  .arg(bytesReceived / (1024*1024))
                                  .arg(speed*1000/(1024*1024),0,'f',2)
                                  .arg(TotalBytes / (1024 * 1024))
                                  .arg(useTime/1000,0,'f',0)
                                  .arg(TotalBytes/speed/1000 - useTime/1000,0,'f',0));

if(bytesReceived == TotalBytes)
{
    localFile->close();
    tcpClient->close();
    ui->tcpClientStatusLabel->setText(tr("")
                                      .arg(fileName));
}

}

分别右击取消和关闭按钮转到槽,在槽中添加代码
错误处理、取消按钮、关闭按钮、关闭事件 的函数代码
// 错误处理
void TcpClient::displayError(QAbstractSocket::SocketError socketError)
{
switch(socketError)
{
case QAbstractSocket::RemoteHostClosedError : break;
default : qDebug() << tcpClient->errorString();
}
}

// 取消按钮
void TcpClient::on_tcpClientCancleBtn_clicked()
{
tcpClient->abort();
if (localFile->isOpen())
localFile->close();
}

// 关闭按钮
void TcpClient::on_tcpClientCloseBtn_clicked()
{
tcpClient->abort();
if (localFile->isOpen())
localFile->close();
close();
}

// 关闭事件
void TcpClient::closeEvent(QCloseEvent *)
{
on_tcpClientCloseBtn_clicked();
}

新建文件,Qt 》》 Qt 设计师界面类,界面模板选择Dialog without Buttons,类名为TcpServer

进入设计模式,在tcpcient.ui界面中添加控件

在tcpserver.h文件中头文件、私有变量和函数声明等
#include
class QFile;
class QTcpServer;
class QTcpSocket;
void initServer();
void refused();

protected:
void closeEvent(QCloseEvent *);

private:
Ui::TcpServer *ui;

qint16 tcpPort;
QTcpServer *tcpServer;
QString fileName;
QString theFileName;
QFile *localFile;

qint64 TotalBytes;
qint64 bytesWritten;
qint64 bytesToWrite;
qint64 payloadSize;
QByteArray outBlock;

QTcpSocket *clientConnection;

QTime time;

private slots:
void sendMessage();
void updateClientProgress(qint64 numBytes);

void on_serverOpenBtn_clicked();

void on_serverSendBtn_clicked();

void on_serverCloseBtn_clicked();

signals:
void sendFileName(QString fileName);

在在tcpserver.cpp文件中添加代码
头文件
#include
#include
#include
#include
#include
#include

构造函数中添加代码
tcpPort = 6666;
tcpServer = new QTcpServer(this);
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendMessage()));

initServer();

声明函数代码
// 初始化
void TcpServer::initServer()
{
payloadSize = 64*1024;
TotalBytes = 0;
bytesWritten = 0;
bytesToWrite = 0;

ui->progressBar->reset();
ui->serverOpenBtn->setEnabled(true);
ui->serverSendBtn->setEnabled(false);

tcpServer->close();

}

// 开始发送数据
void TcpServer::sendMessage()
{
ui->serverSendBtn->setEnabled(false);
clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, SIGNAL(bytesWritten(qint64)),
this, SLOT(updateClientProgress(qint64)));

// ui->serverStatusLabel->setText(tr("").arg(theFileName));

localFile = new QFile(fileName);
if(!localFile->open((QFile::ReadOnly))){
    QMessageBox::warning(this, tr(""), tr("")
                         .arg(fileName).arg(localFile->errorString()));
    return;
}
TotalBytes = localFile->size();
QDataStream sendOut(&outBlock, QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_4_7);
time.start();  // 开始计时
QString currentFile = fileName.right(fileName.size()
                                     - fileName.lastIndexOf('/')-1);
sendOut << qint64(0) << qint64(0) << currentFile;
TotalBytes += outBlock.size();
sendOut.device()->seek(0);
sendOut << TotalBytes << qint64((outBlock.size() - sizeof(qint64)*2));
bytesToWrite = TotalBytes - clientConnection->write(outBlock);
outBlock.resize(0);

}

// 更新进度条
void TcpServer::updateClientProgress(qint64 numBytes)
{
qApp->processEvents();
bytesWritten += (int)numBytes;
if (bytesToWrite > 0) {
outBlock = localFile->read(qMin(bytesToWrite, payloadSize));
bytesToWrite -= (int)clientConnection->write(outBlock);
outBlock.resize(0);
} else {
localFile->close();
}
ui->progressBar->setMaximum(TotalBytes);
ui->progressBar->setValue(bytesWritten);

float useTime = time.elapsed();
double speed = bytesWritten / useTime;
ui->serverStatusLabel->setText(tr("")
               .arg(bytesWritten / (1024*1024))
               .arg(speed*1000 / (1024*1024), 0, 'f', 2)
               .arg(TotalBytes / (1024 * 1024))
               .arg(useTime/1000, 0, 'f', 0)
               .arg(TotalBytes/speed/1000 - useTime/1000, 0, 'f', 0));

if(bytesWritten == TotalBytes) {
    localFile->close();
    tcpServer->close();
    ui->serverStatusLabel->setText(tr("").arg(theFileName));
}

}
右击各个按钮转到槽,在槽中添加代码
// 打开按钮
void TcpServer::on_serverOpenBtn_clicked()
{
fileName = QFileDialog::getOpenFileName(this);
if(!fileName.isEmpty())
{
theFileName = fileName.right(fileName.size() - fileName.lastIndexOf(’/’)-1);
ui->serverStatusLabel->setText(tr(" ").arg(theFileName));
ui->serverSendBtn->setEnabled(true);
ui->serverOpenBtn->setEnabled(false);
}
}

// 发送按钮
void TcpServer::on_serverSendBtn_clicked()
{
if(!tcpServer->listen(QHostAddress::Any,tcpPort))//开始监听
{
qDebug() << tcpServer->errorString();
close();
return;
}

ui->serverStatusLabel->setText(tr(""));
emit sendFileName(theFileName);

}

// 关闭按钮
void TcpServer::on_serverCloseBtn_clicked()
{
if(tcpServer->isListening())
{
tcpServer->close();
if (localFile->isOpen())
localFile->close();
clientConnection->abort();
}
close();
}

// 被对方拒绝
void TcpServer::refused()
{
tcpServer->close();
ui->serverStatusLabel->setText(tr(""));
}

// 关闭事件
void TcpServer::closeEvent(QCloseEvent *)
{
on_serverCloseBtn_clicked();
}

在widget.h中添加代码
class QUdpSocket;

class TcpServer;
#include

enum MessageType{Message, NewParticipant, ParticipantLeft, FileName, Refuse};

protected:
void newParticipant(QString userName,
QString localHostName, QString ipAddress);
void participantLeft(QString userName,
QString localHostName, QString time);
void sendMessage(MessageType type, QString serverAddress="");

QString getIP();
QString getUserName();
QString getMessage();


void hasPendingFile(QString userName, QString serverAddress,
                    QString clientAddress, QString fileName);

bool saveFile(const QString& fileName);

void closeEvent(QCloseEvent *);

private:
Ui::Widget *ui;
QUdpSocket *udpSocket;
qint16 port;

QString fileName;
TcpServer *server;

QColor color;

private slots:
void processPendingDatagrams();

void on_sendButton_clicked();

void getFileName(QString);
void on_sendToolBtn_clicked();
void on_fontComboBox_currentFontChanged(QFont f);
void on_sizeComboBox_currentIndexChanged(QString );
void on_boldToolBtn_clicked(bool checked);
void on_italicToolBtn_clicked(bool checked);
void on_underlineToolBtn_clicked(bool checked);
void on_colorToolBtn_clicked();

void currentFormatChanged(const QTextCharFormat &format);
void on_saveToolBtn_clicked();
void on_clearToolBtn_clicked();
void on_exitButton_clicked();

在widget.cpp中添加代码
头文件
#include
#include
#include
#include
#include
#include
#include

#include “tcpserver.h”
#include “tcpclient.h”
#include

#include

构造函数中添加代码

udpSocket = new QUdpSocket(this);
port = 45454;
udpSocket->bind(port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
sendMessage(NewParticipant);

server = new TcpServer(this);
connect(server, SIGNAL(sendFileName(QString)), this, SLOT(getFileName(QString)));

connect(ui->messageTextEdit, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
        this, SLOT(currentFormatChanged(const QTextCharFormat)));

各个声明函数代码
// 使用UDP广播发送信息
void Widget::sendMessage(MessageType type, QString serverAddress)
{
QByteArray data;
QDataStream out(&data, QIODevice::WriteOnly);
QString localHostName = QHostInfo::localHostName();
QString address = getIP();
out << type << getUserName() << localHostName;

switch(type)
{
case Message :
    if (ui->messageTextEdit->toPlainText() == "") {
        QMessageBox::warning(0,tr(""),tr(""),QMessageBox::Ok);
        return;
    }
    out << address << getMessage();
    ui->messageBrowser->verticalScrollBar()
            ->setValue(ui->messageBrowser->verticalScrollBar()->maximum());
    break;

case NewParticipant :
    out << address;
    break;

case ParticipantLeft :
    break;

case FileName : {
    int row = ui->userTableWidget->currentRow();
    QString clientAddress = ui->userTableWidget->item(row, 2)->text();
    out << address << clientAddress << fileName;
    break;
}

case Refuse :
    out << serverAddress;
    break;
}
udpSocket->writeDatagram(data,data.length(),QHostAddress::Broadcast, port);

}

// 接收UDP信息
void Widget::processPendingDatagrams()
{
while(udpSocket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
QDataStream in(&datagram, QIODevice::ReadOnly);
int messageType;
in >> messageType;
QString userName,localHostName,ipAddress,message;
QString time = QDateTime::currentDateTime()
.toString(“yyyy-MM-dd hh:mm:ss”);

    switch(messageType)
    {
    case Message:
        in >> userName >> localHostName >> ipAddress >> message;
        ui->messageBrowser->setTextColor(Qt::blue);
        ui->messageBrowser->setCurrentFont(QFont("Times New Roman",12));
        ui->messageBrowser->append("[ " +userName+" ] "+ time);
        ui->messageBrowser->append(message);
        break;

    case NewParticipant:
        in >>userName >>localHostName >>ipAddress;
        newParticipant(userName,localHostName,ipAddress);
        break;

    case ParticipantLeft:
        in >>userName >>localHostName;
        participantLeft(userName,localHostName,time);
        break;

    case FileName: {
        in >> userName >> localHostName >> ipAddress;
        QString clientAddress, fileName;
        in >> clientAddress >> fileName;
        hasPendingFile(userName, ipAddress, clientAddress, fileName);
        break;
    }

    case Refuse: {
        in >> userName >> localHostName;
        QString serverAddress;
        in >> serverAddress;
        QString ipAddress = getIP();

        if(ipAddress == serverAddress)
        {
            server->refused();
        }
        break;
    }
    }
}

}

// 处理新用户加入
void Widget::newParticipant(QString userName, QString localHostName, QString ipAddress)
{
bool isEmpty = ui->userTableWidget->findItems(localHostName, Qt::MatchExactly).isEmpty();
if (isEmpty) {
QTableWidgetItem *user = new QTableWidgetItem(userName);
QTableWidgetItem *host = new QTableWidgetItem(localHostName);
QTableWidgetItem *ip = new QTableWidgetItem(ipAddress);

    ui->userTableWidget->insertRow(0);
    ui->userTableWidget->setItem(0,0,user);
    ui->userTableWidget->setItem(0,1,host);
    ui->userTableWidget->setItem(0,2,ip);
    ui->messageBrowser->setTextColor(Qt::gray);
    ui->messageBrowser->setCurrentFont(QFont("Times New Roman",10));
    ui->messageBrowser->append(tr("%1 在线!").arg(userName));
    ui->userNumLabel->setText(tr("在线人数:%1").arg(ui->userTableWidget->rowCount()));

    sendMessage(NewParticipant);
}

}

// 处理用户离开
void Widget::participantLeft(QString userName, QString localHostName, QString time)
{
int rowNum = ui->userTableWidget->findItems(localHostName, Qt::MatchExactly).first()->row();
ui->userTableWidget->removeRow(rowNum);
ui->messageBrowser->setTextColor(Qt::gray);
ui->messageBrowser->setCurrentFont(QFont(“Times New Roman”, 10));
ui->messageBrowser->append(tr("%1 于 %2 离开!").arg(userName).arg(time));
ui->userNumLabel->setText(tr(“在线人数:%1”).arg(ui->userTableWidget->rowCount()));
}

// 获取ip地址
QString Widget::getIP()
{
QList list = QNetworkInterface::allAddresses();
foreach (QHostAddress address, list) {
if(address.protocol() == QAbstractSocket::IPv4Protocol)
return address.toString();
}
return 0;
}

// 获取用户名
QString Widget::getUserName()
{
QStringList envVariables;
envVariables << “USERNAME." << "USER.” << “USERDOMAIN."
<< "HOSTNAME.
” << “DOMAINNAME.*”;
QStringList environment = QProcess::systemEnvironment();
foreach (QString string, envVariables) {
int index = environment.indexOf(QRegExp(string));
if (index != -1) {
QStringList stringList = environment.at(index).split(’=’);
if (stringList.size() == 2) {
return stringList.at(1);
break;
}
}
}
return “unknown”;
}

// 获得要发送的消息
QString Widget::getMessage()
{
QString msg = ui->messageTextEdit->toHtml();

ui->messageTextEdit->clear();
ui->messageTextEdit->setFocus();
return msg;

}

// 发送消息
void Widget::on_sendButton_clicked()
{
sendMessage(Message);
}

// 获取要发送的文件名
void Widget::getFileName(QString name)
{
fileName = name;
sendMessage(FileName);
}

// 传输文件按钮
void Widget::on_sendToolBtn_clicked()
{
if(ui->userTableWidget->selectedItems().isEmpty())
{
QMessageBox::warning(0, tr(“选择用户”),
tr(“请先从用户列表选择要传送的用户!”), QMessageBox::Ok);
return;
}
server->show();
server->initServer();
}

// 是否接收文件
void Widget::hasPendingFile(QString userName, QString serverAddress,
QString clientAddress, QString fileName)
{
QString ipAddress = getIP();
if(ipAddress == clientAddress)
{
int btn = QMessageBox::information(this,tr(“接受文件”),
tr(“来自%1(%2)的文件:%3,是否接收?”)
.arg(userName).arg(serverAddress).arg(fileName),
QMessageBox::Yes,QMessageBox::No);
if (btn == QMessageBox::Yes) {
QString name = QFileDialog::getSaveFileName(0,tr(“保存文件”),fileName);
if(!name.isEmpty())
{
TcpClient *client = new TcpClient(this);
client->setFileName(name);
client->setHostAddress(QHostAddress(serverAddress));
client->show();
}
} else {
sendMessage(Refuse, serverAddress);
}
}
}

// 更改字体族
void Widget::on_fontComboBox_currentFontChanged(QFont f)
{
ui->messageTextEdit->setCurrentFont(f);
ui->messageTextEdit->setFocus();
}

// 更改字体大小
void Widget::on_sizeComboBox_currentIndexChanged(QString size)
{
ui->messageTextEdit->setFontPointSize(size.toDouble());
ui->messageTextEdit->setFocus();
}

// 加粗
void Widget::on_boldToolBtn_clicked(bool checked)
{
if(checked)
ui->messageTextEdit->setFontWeight(QFont::Bold);
else
ui->messageTextEdit->setFontWeight(QFont::Normal);
ui->messageTextEdit->setFocus();
}

// 倾斜
void Widget::on_italicToolBtn_clicked(bool checked)
{
ui->messageTextEdit->setFontItalic(checked);
ui->messageTextEdit->setFocus();
}

// 下划线
void Widget::on_underlineToolBtn_clicked(bool checked)
{
ui->messageTextEdit->setFontUnderline(checked);
ui->messageTextEdit->setFocus();
}

// 颜色
void Widget::on_colorToolBtn_clicked()
{
color = QColorDialog::getColor(color, this);
if (color.isValid()) {
ui->messageTextEdit->setTextColor(color);
ui->messageTextEdit->setFocus();
}
}

void Widget::currentFormatChanged(const QTextCharFormat &format)
{
ui->fontComboBox->setCurrentFont(format.font());

// 如果字体大小出错(因为我们最小的字体为9),使用12
if (format.fontPointSize() < 9) {
    ui->sizeComboBox->setCurrentIndex(3);
} else {
    ui->sizeComboBox->setCurrentIndex( ui->sizeComboBox
                                      ->findText(QString::number(format.fontPointSize())));
}
ui->boldToolBtn->setChecked(format.font().bold());
ui->italicToolBtn->setChecked(format.font().italic());
ui->underlineToolBtn->setChecked(format.font().underline());
color = format.foreground().color();

}

// 保存聊天记录
void Widget::on_saveToolBtn_clicked()
{
if (ui->messageBrowser->document()->isEmpty()) {
QMessageBox::warning(0, tr(“警告”), tr(“聊天记录为空,无法保存!”), QMessageBox::Ok);
} else {
QString fileName = QFileDialog::getSaveFileName(this,
tr(“保存聊天记录”), tr(“聊天记录”), tr(“文本(.txt);;All File(.*)”));
if(!fileName.isEmpty())
saveFile(fileName);
}
}

// 保存聊天记录
bool Widget::saveFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr(“保存文件”),
tr(“无法保存文件 %1:\n %2”).arg(fileName)
.arg(file.errorString()));
return false;
}
QTextStream out(&file);
out << ui->messageBrowser->toPlainText();

return true;

}

// 清空聊天记录
void Widget::on_clearToolBtn_clicked()
{
ui->messageBrowser->clear();
}

// 退出按钮
void Widget::on_exitButton_clicked()
{
close();
}

// 关闭事件
void Widget::closeEvent(QCloseEvent *e)
{
sendMessage(ParticipantLeft);
QWidget::closeEvent(e);
}

进入设计模式,在widget.ui界面中添加控件

新建资源,名称为images

第十二步,向资源中添加图片

在pro文件中添加代码
QT += network:
RC_ICONS=myapp.ico

运行程序,具体结果如图所示
1.主界面

2.发送消息

3.改变字体格式

4.选择颜色对话框

5.发送文件

6.保存聊天记录
【选择保存位置】

猜你喜欢

转载自blog.csdn.net/weixin_43372169/article/details/110928254