1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Linux系统开发|QT制作聊天软件实验报告

Linux系统开发|QT制作聊天软件实验报告

时间:2024-06-22 18:55:36

相关推荐

Linux系统开发|QT制作聊天软件实验报告

一、实验目的

设计一款携带多种功能的聊天软件,不仅可以聊天,也能修改字体,计时,绘画等等。

二、实验内容:

1)ui设计(满分15分)

2)画图、timer、多线程(满分20分)

3)数据库操作(满分15分)

4)TCP网络通信(满分40分) (客户端15分,多线程服务器25分)

三、实验环境

Qt Creator 4.2.1 (Community)

四、实验过程与运行结果

1)ui设计

图表 1聊天界面

头像是在网络上找的,其余图标都是自己绘制的,但由于设计时间过早,在后面完成代码的时候发现没有信息的数据库,所以这里的了解成员要改为查找地址。

图表 2设计界面2

这是设计的第二个界面,但是本来想要管理员链接服务端,但是因为项目的问题一直链接不上,排查问题找了很久都没有找到问题,所以这里设计的按钮其实是无法跳转的,所以就改为第一次的设计。

图表 3绘画界面

图表 4客户端界面

图表 5服务端界面

2)画图、timer、多线程

图表 6多线程聊天

可进行多人聊天,只要打开窗口就能够聊天,但如果其他人要接收的话,也需要打开聊天框,不然就不能够接收到信息。

图表 7保存聊天记录

这里为了合理化也设计了字体样式的更改,保存,清空等等,但是颜色字号因为不太理解所以没有做成功,但加粗等成功了。

图表 8保存的聊天记录

图表 9修改字体样式

图表 10警告

为了不出现重复聊天框的BUG,所以要设置一个警告。

图表 11绘图界面

这里只绘制了一个圈和字体,但也可以实现其他的绘画,比如画直线等等,但需要在代码中加入,这里没有加是因为我觉得这样设计会比较好看。

图表 12绘画界面弹出

只要点击来画画吧,就会弹出绘画的这个窗口,这里本来想设计成后面的那些窗口都消失,但发现这样不太明显,就将那条代码删除了。

图表 13计时器

点击计时器按钮,就会跳转到计时器的这个页面来,点击开始就能够开始计时,停止就停止计时,重置就是重新开始。

图表 14点击重置后

点击重置后,时间就归零了。

3)数据库操作

图表 15数据库登录

这里是老师上课讲解的内容,这里进行了一个结合,只要点击右下方的按钮,就能够弹出这个页面,也就是“小蜜蜂数据”,接着就能够链接数据库查询信息了。

图表 16查询信息页面

因为没有数据库,所以这里用的是老师之前教课时所使用的,自己也尝试建立数据库,发现了很多问题,诸如数据的问题,要创建ID类但是一直无法设置好,导致程序出现故障等等。

图表 17重新建立数据库界面

因为原本数据库不太适合我的聊天软件,于是进行了更改,这样就能够查询好友的信息,比较匹配我的聊天软件。

4)TCP网络通信

图表 18同时打开服务端和客户端

能够运行服务端和客户端,界面上的LOGO是我设计的小蜜蜂。

图表 19多线程链接

两个客户端能够和服务端链接并且发送消息。

图表 20单线程链接

以下是主代码展示:【代码不全】

(1)Widegt.cpp#include "widget.h"#include "ui_widget.h"#include"draw.h"#include "mytime.h"#include "mydb.h"#include <QString>#include <QDataStream>#include <QMessageBox>#include <QDateTime>#include <QDebug>#include <QFont>#include <QColor>#include <QColorDialog>#include <QFileDialog>#include <QTextStream>#include <QFontDialog>#include <QPushButton>Widget::Widget(QWidget *parent ,QString name) :QWidget(parent),ui(new Ui::Widget){ui->setupUi(this);myname=name;this->ppage2=new draw;//实例化绘画页面Sconnect(ui->drawBtn,&QPushButton::clicked,[=](){//this->hide();this->ppage2->show();//显示});this->ppage3=new mytime;connect(ui->timerBtn,&QPushButton::clicked,[=](){this->ppage3->show();});this->ppage4=new mydb;connect(ui->dataBtn,&QPushButton::clicked,[=](){this->ppage4->show();});this->port=0032;this->udpSocket=new QUdpSocket(this);udpSocket->bind(this->port,QUdpSocket::ShareAddress |QUdpSocket::ReuseAddressHint);connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::ReceiveMessage);connect(ui->sendBtn,&QPushButton::clicked,[=](){sndMsg(Msg);});}void Widget::sndMsg(Widget::Msgtype type){QByteArray array;QDataStream stream(&array,QIODevice::WriteOnly);stream<<type<<this->getName();switch(type){case Msg:if(ui->msgTxtEdit->toPlainText()==""){QMessageBox::warning(this,"警告","发送的内容不能为空!");return;}stream<<this->getMsg();break;case UserEnter:break;case UserLeft:break;}udpSocket->writeDatagram(array.data(),array.size(),QHostAddress::Broadcast,this->port);}QString Widget::getName(){return this->myname;}QString Widget::getMsg(){QString msg=ui->msgTxtEdit->toHtml();ui->msgTxtEdit->clear();ui->msgTxtEdit->setFocus();return msg;}void Widget::ReceiveMessage(){qint64 size=udpSocket->pendingDatagramSize();int mysize=static_cast<int>(size);QByteArray *array=new QByteArray(mysize,0);udpSocket->readDatagram((*array).data(),size);QDataStream stream(array,QIODevice::ReadOnly);int mytype;QString name,msg;//聊天内容 用户名QString time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");stream>>mytype;switch(mytype){case Msg:stream>>name>>msg;ui->msgBrowser->setTextColor(QColor(Qt::blue));ui->msgBrowser->setCurrentFont(QFont("Times New Roman",10));ui->msgBrowser->append(("["+name+"]"+time));ui->msgBrowser->append(msg);break;case UserEnter:stream>>name;// userEnter(name);break;case UserLeft:stream>>name;// userLeft(name,time);break;}//字体改变connect(ui->fontCbx,&QFontComboBox::currentFontChanged,[=](const QFont &font){ui->msgTxtEdit->setFontFamily(font.toString());ui->msgTxtEdit->setFocus();});//字体大小void (QComboBox:: *sizebtn)(const QString &text)=&QComboBox::currentTextChanged;connect(ui->sizeCbx,sizebtn,[=](const QString &text){ui->msgTxtEdit->setFontPointSize(text.toDouble());ui->msgTxtEdit->setFocus();});//加粗connect(ui->boldTBtn,&QToolButton::clicked,this,[=](bool checked){if(checked){ui->msgTxtEdit->setFontWeight(QFont::Bold);}else{ui->msgTxtEdit->setFontWeight(QFont::Normal);}});//倾斜connect(ui->italicTbtn,&QToolButton::clicked,this,[=](bool checked){ui->msgTxtEdit->setFontItalic(checked);ui->msgTxtEdit->setFocus();});//下划线connect(ui->underlineTBtn,&QToolButton::clicked,this,[=](bool checked){ui->msgTxtEdit->setFontUnderline(checked);ui->msgTxtEdit->setFocus();});//清除connect(ui->clearTBtn,&QToolButton::clicked,[=](){ui->msgBrowser->clear();});//颜色connect(ui->colorTBtn,&QToolButton::clicked,this,[=](){QColor color=QColorDialog::getColor(color,this);ui->msgBrowser->clear();});//保存connect(ui->saveTBtn,&QToolButton::clicked,[=](){if(ui->msgBrowser->document()->isEmpty()){QMessageBox::warning(this,"警告","保存内容不能为空!");return;}else{QString filename=QFileDialog::getSaveFileName(this,"保存聊天记录","聊天记录","(*.txt");if(!filename.isEmpty()){QFile file(filename);file.open(QIODevice::WriteOnly |QFile::Text);QTextStream stream(&file);stream<<ui->msgBrowser->toPlainText();file.close();}}});}void Widget::closeEvent(QCloseEvent *){emit this->closeWidget();}Widget::~Widget(){delete ui;}(2)Wedget.h#ifndef WIDGET_H#define WIDGET_H#include "draw.h"#include <QWidget>#include <QUdpSocket>#include "mytime.h"#include "mydb.h"namespace Ui {class Widget;}class Widget : public QWidget{Q_OBJECTpublic:enum Msgtype{Msg,UserEnter,UserLeft};explicit Widget(QWidget *parent, QString name);void sndMsg(Msgtype type);QString getName();QString getMsg();QString getIcon();void userEnter(QString username);void userLeft(QString username,QString time);void ReceiveMessage();~Widget();draw *ppage2=NULL;//用来保存绘画界面的实例化对象地址mytime *ppage3=NULL;//计时器mydb *ppage4=NULL;//数据库signals:void closeWidget();void showmain();private:Ui::Widget *ui;quint16 port;QString myname;QUdpSocket *udpSocket;public:void closeEvent(QCloseEvent *);};#endif // WIDGET_H(3)denglu.cpp#include "denglu.h"#include "ui_denglu.h"#include <QIcon>#include <QToolButton>#include <QList>#include <QString>#include <widget.h>#include <QMessageBox>denglu::denglu(QWidget *parent) :QDialog(parent),ui(new Ui::denglu){ui->setupUi(this);//图标this->setWindowIcon(QIcon(":/image/bee.PNG"));//名称this->setWindowTitle("小蜜蜂聊天");QList<QString> namelist;namelist<<"喝饮料的小熊猫"<<"今天很开心"<<"保佑及格!"<<"天选锦鲤在哪里"<<"好好学习天天向上";QStringList iconNameList;iconNameList<<"1"<<"2"<<"3"<<"4"<<"5";QVector<QToolButton *> vector;for(int i=0;i<5;i++){QToolButton *btn=new QToolButton(this);//头像btn->setIcon(QPixmap(QString(":/image/%1.png").arg(iconNameList[i])));btn->setIconSize(QPixmap((QString(":/image/%1.png").arg(iconNameList[i]))).size());btn->setText(QString("%1").arg(namelist[i]));btn->setAutoRaise(true);btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);ui->vlayout_2->addWidget(btn);vector.push_back(btn);IsShow.push_back(false);}for(int i=0;i<5;i++){connect(vector[i],&QToolButton::clicked,[=](){if(IsShow[i]){QMessageBox::warning(this,"警告","已有相关聊天框,请勿重复点击!");return;}IsShow[i]=true;Widget *widget=new Widget(nullptr,vector[i]->text());widget->setWindowIcon(vector[i]->icon());widget->setWindowTitle(vector[i]->text());widget->show();connect(widget,&Widget::closeWidget,this,[=](){IsShow[i]=false;});});}}denglu::~denglu(){delete ui;}(4)denglu.h#ifndef DENGLU_H#define DENGLU_H#include <QDialog>namespace Ui {class denglu;}class denglu : public QDialog{Q_OBJECTpublic:explicit denglu(QWidget *parent = 0);~denglu();private:Ui::denglu *ui;QVector<bool> IsShow;};#endif // DENGLU_H(5)draw.cpp#include "draw.h"#include "ui_draw.h"#include <QPainter>#include"qpainter.h"draw::draw(QWidget *parent) :QMainWindow(parent),ui(new Ui::draw){ui->setupUi(this);this->setWindowIcon(QIcon(":/image/bee.PNG"));this->setWindowTitle("小蜜蜂绘画");}draw::~draw(){delete ui;}void draw::paintEvent(QPaintEvent *event){Q_UNUSED(event);QPainter painter(this);// 设置画笔颜色painter.setPen(QColor(0, 160, 230));// 设置字体:微软雅黑、点大小50、斜体QFont font;font.setFamily("Microsoft YaHei");font.setPointSize(50);font.setItalic(true);painter.setFont(font);// 绘制文本painter.drawText(rect(), Qt::AlignCenter, "小蜜蜂");Q_UNUSED(event);painter.begin(this);QRectF rectangle(150.0, 100.0, 280.0, 240.0);//如果是一个正方形那就是一个圆painter.drawEllipse(rectangle);painter.end();}(6)mytime.cpp#include "mytime.h"#include "ui_mytime.h"#include <QTimer>#include <QTime>#include <QDebug>mytime::mytime(QWidget *parent) :QMainWindow(parent),ui(new Ui::mytime){ui->setupUi(this);this->setWindowIcon(QIcon(":/image/bee.PNG"));this->setWindowTitle("小蜜蜂计时器");time.setHMS(0,0,0,0);//设置初始值timer = new QTimer(this);//创建一个定时器connect(timer, SIGNAL(timeout()), this, SLOT(update()));}mytime::~mytime(){delete ui;}void mytime::update(){static quint32 time_out=0;time_out++;time=time.addSecs(1);ui->label->setText(time.toString("hh:mm:ss"));}void mytime::on_startBtn_clicked(){timer->start(1000);}void mytime::on_stopBtn_clicked(){timer->stop();}void mytime::on_reBtn_clicked(){timer->stop();time.setHMS(0,0,0,0);ui->label->setText(time.toString("hh:mm:ss"));}(7)mserver.cpp#include "mserver.h"#include "ui_mserver.h"mServer::mServer(QWidget *parent) :QWidget(parent),ui(new Ui::mServer){ui->setupUi(this);this->setWindowIcon(QIcon(":/image/bee.PNG"));this->setWindowTitle("小蜜蜂服务端");list_sock.clear();mserver=new QTcpServer();connect(mserver,SIGNAL(newConnection()),this,SLOT(acceptListen()));ui->tabClient->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);mtype=msize=0;mdata.clear();}mServer::~mServer(){delete ui;}void mServer::sendData(){int rows=ui->tabClient->rowCount();if(rows<1) return;int row=ui->tabClient->currentIndex().row();list_sock[row]->write(mdata);mdata.clear();}void mServer::processData(int id){}void mServer::acceptListen(){QTcpSocket *sock=mserver->nextPendingConnection();list_sock.append(sock);connect(sock,SIGNAL(readyRead()),this,SLOT(recvData()));int rows=ui->tabClient->rowCount();ui->tabClient->insertRow(rows);ui->tabClient->setItem(rows,0, new QTableWidgetItem(sock->peerAddress().toString()));ui->tabClient->setItem(rows,1, new QTableWidgetItem(QString::number(sock->peerPort())));QString str=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");ui->tabClient->setItem(rows,2, new QTableWidgetItem(str));}void mServer::recvData(){QTcpSocket *sock = (QTcpSocket*)sender();for(int i=0;i<list_sock.length();i++){if(sock == list_sock[i]){QString str=sock->peerAddress().toString()+"---"+QString::number(sock->peerPort())+":";QString str1 = QString::fromLocal8Bit(sock->readAll());ui->textEdit->append(str);ui->textEdit->append(str1);}}}void mServer::on_btn_listen_clicked(){if(!mserver->listen(QHostAddress::Any,22233)){qDebug()<<mserver->errorString();//>>log.txtreturn;}}void mServer::on_btn_discon_clicked(){mserver->close();for(int i=0;i<list_sock.length();i++){list_sock[i]->abort(); //disconnect}list_sock.clear();exit(0);}void mServer::on_btn_sendMsg_clicked(){QDataStream out(&mdata,QIODevice::WriteOnly); //memcpyout.setVersion(QDataStream::Qt_5_8);mtype=101; //101 102 103 201 202QString str=ui->text_send->text();QByteArray ba=str.toLocal8Bit();msize=ba.length();out<<mtype; out<<msize;mdata.append(ba);ba.clear();sendData();}void mServer::on_btn_sendFile_clicked(){QString fpath=QFileDialog::getOpenFileName();if(fpath.isEmpty()) return;mtype= (fpath.endsWith("jpg"))?103:102;QFile mfile(fpath);QByteArray data;if(!mfile.isOpen()){mfile.open(QIODevice::ReadOnly);data = mfile.readAll();}mfile.close();msize=data.length();mdata.clear();QDataStream out(&mdata,QIODevice::WriteOnly); //memcpyout.setVersion(QDataStream::Qt_5_8);out<<mtype; out<<msize;mdata.append(data);qDebug()<<mtype<<msize;sendData();}(8)mclient.cpp#include "mclient.h"#include "ui_mclient.h"mclient::mclient(QWidget *parent) :QWidget(parent),ui(new Ui::mclient){ui->setupUi(this);this->setWindowIcon(QIcon(":/image/bee.PNG"));this->setWindowTitle("小蜜蜂客户端");sock=new QTcpSocket();connect(sock,SIGNAL(readyRead()),this,SLOT(recvData()));size=recvsize=totalsize=mtype=0;send_data.clear();devid=locid=0;list_random.clear();}mclient::~mclient(){delete ui;}void mclient::processData(){if(mtype == 101){ui->text_recv->clear();ui->text_recv->append(QString::fromLocal8Bit(mdata));}if(mtype == 102){ui->text_recv->clear();ui->text_recv->append(QString::fromLocal8Bit(mdata));}if(mtype == 103){QBuffer buffer(&mdata);buffer.open( QIODevice::ReadOnly);QImageReader reader(&buffer, "jpg");QImage image = reader.read();QImage img=image.scaled(ui->labImg->rect().width(),ui->labImg->rect().height(),Qt::IgnoreAspectRatio);ui->labImg->clear();ui->labImg->setPixmap(QPixmap::fromImage(img));}}void mclient::recvData(){if(sock->bytesAvailable()<8) return; //type sizeif(totalsize < 1){QDataStream in(sock);in.setVersion(QDataStream::Qt_5_8);in>>mtype; in>>totalsize; mdata.clear(); //cont 25kqDebug()<<mtype;}if(recvsize<totalsize){quint32 len=(quint32)sock->bytesAvailable();recvsize += len;mdata.append(sock->readAll());if(recvsize == totalsize){processData();}}}void mclient::on_btn_con_clicked(){sock->connectToHost(ui->textIP->text(),(quint16)ui->textPort->text().toUInt());}void mclient::on_btn_send_clicked(){QDataStream out(&send_data,QIODevice::WriteOnly); //memcpyout.setVersion(QDataStream::Qt_5_8);// mtype=201; //101 102 103 201 202QString str=ui->lineEdit->text();QByteArray ba=str.toLocal8Bit();// size=ba.length();// out<<mtype; out<<size;send_data.clear();send_data.append(ba);ba.clear();sock->write(send_data);send_data.clear();}void mclient::on_btn_discon_clicked(){sock->abort();exit(0);}void mclient::on_btn_gendata_clicked(){devid=(quint8)(ui->text_devid->text().toInt());locid=(quint8)(ui->text_locid->text().toInt());float a=1.0; float b=100.0; mtype=size=0;for(int i=0;i<7;i++){QTime t= QTime::currentTime();qsrand(t.msec()+t.second()*100);list_random.append(qrand());QThread::msleep(30);}float v1=(float)((450+list_random[0]%100)*a);float v2=(float)((20+list_random[1]%50)*a);float v3=(float)((100+list_random[2]%400)*a);float v4=(float)((5+list_random[3]%25)*a);float v5=(float)((5+list_random[4]%20)*a);float v6=(float)((26+list_random[5]%7)*a);float v7=(float)((85+list_random[6]%7)/b);send_data.clear();mtype=222;QByteArray ba; ba.clear();QDataStream out1(&ba,QIODevice::WriteOnly);out1.setVersion(QDataStream::Qt_5_8);out1<<devid<<locid<<v1<<v2<<v3<<v4<<v5<<v6<<v7;size=(quint32)ba.length();QDataStream out(&send_data,QIODevice::WriteOnly);out1.setVersion(QDataStream::Qt_5_8);out<<mtype<<size;send_data.append(ba);sock->write(send_data);// qDebug()<<mtype<<size<<devid<<locid<<v1<<v2<<v3<<v4<<v5<<v6<<v7;send_data.clear();}

五、实验总结

在本次实践学习中,我运用上课学习到的知识进行了自己的设计制作,会发现当跟着老师的时候会觉得很轻松的事情,自己上手了却变得困难了,比如多线程这一块内容,跟着老师走的时候就会知道下一步应该走向哪里,但是自己打开的时候却经常报错,而且因为地址的问题要找很多的资料,反复去回忆老师所讲过的内容,因为要复制一些程序到源地址中,而这几个程序我印象不深,所以也导致了在这个问题上面浪费太多时间,这也让我决定以后类似于这样的知识点应该记录到笔记中去。

还有就是手动建槽的时候也要注意规范,之前因为想测试某个功能,忘记在头文件中加入槽,等反应过来之后再去添加槽,却发现还是运行不了,代码也找了很多参考,但是都没有能够找出问题,所以这一个内容我全部删除重新再打一次代码,而后就运行成功了,所以我也认识到规范性也是很重要的。

在最初的UI设计中我是参考别人的设计,和同学一起讨论设计出来的,但发现功能太少了,远远不符合要求,所以再翻找以前的学习代码去找该怎么实现我想要的功能,然后再进行设计,所以在最初设计的基础上做了很多变动,比如因为没有数据库,所以和我最先设想的查找好友资料也无法做出来,只能参考原来上课时候的学习代码进行制作,还有原本想要管理员按钮连接服务端进行跳转,却发现服务端需要单独开设一个项目,那如何把项目放在另一个项目下面我也是找了很多资料,但也一直无法实现,这也是我的一个遗憾,就是无法在一个项目中同时做到多个功能,只能在聊天的基础上搭载绘画,计时器,天气数据查询等的功能。

最后就是代码,其实我参考学习了很多资料,包括之前上课所讲的代码,我都有做参考,在这个过程中也重新学到了很多知识,也算是查缺补漏了,刚开始觉得这个作业很难,但后来一步一步一个一个功能慢慢实现之后,就会发现其实还是能够完成的,每次遇到难题我都会去请教舍友或者网上搜索资料,一步一步试错也让我曾经很崩溃,有时候一整天都在完成一个功能,虽然最后结果出来之后不是很惊艳,但是我觉得我已经做到了我的最好,也学习到了很多!

能做出这个软件,也很感谢:

B站up主:性感的大飞侠-【QT实现群聊聊天系统-哔哩哔哩】 https://b23.tv/yrhCLWL

唔国旗u【04_QT_页面切换(两个ui界面)-哔哩哔哩】 https://b23.tv/wEWbfqW

以上指导很有用!

实验结果存在较多BUG,很不完善!欢迎讨论!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。