生活随笔
收集整理的這篇文章主要介紹了
Linux系统开发|QT制作聊天软件实验报告
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、實驗目的
設(shè)計一款攜帶多種功能的聊天軟件,不僅可以聊天,也能修改字體,計時,繪畫等等。
二、實驗內(nèi)容:
1)ui設(shè)計(滿分15分)
2)畫圖、timer、多線程(滿分20分)
3)數(shù)據(jù)庫操作(滿分15分)
4)TCP網(wǎng)絡(luò)通信(滿分40分) (客戶端15分,多線程服務器25分)
三、實驗環(huán)境
Qt Creator 4.2.1 (Community)
四、實驗過程與運行結(jié)果
1)ui設(shè)計
圖表 1聊天界面
頭像是在網(wǎng)絡(luò)上找的,其余圖標都是自己繪制的,但由于設(shè)計時間過早,在后面完成代碼的時候發(fā)現(xiàn)沒有信息的數(shù)據(jù)庫,所以這里的了解成員要改為查找地址。
圖表 2設(shè)計界面2
這是設(shè)計的第二個界面,但是本來想要管理員鏈接服務端,但是因為項目的問題一直鏈接不上,排查問題找了很久都沒有找到問題,所以這里設(shè)計的按鈕其實是無法跳轉(zhuǎn)的,所以就改為第一次的設(shè)計。
圖表 3繪畫界面
圖表 4客戶端界面
圖表 5服務端界面
2)畫圖、timer、多線程
圖表 6多線程聊天
可進行多人聊天,只要打開窗口就能夠聊天,但如果其他人要接收的話,也需要打開聊天框,不然就不能夠接收到信息。
圖表 7保存聊天記錄
這里為了合理化也設(shè)計了字體樣式的更改,保存,清空等等,但是顏色字號因為不太理解所以沒有做成功,但加粗等成功了。
圖表 8保存的聊天記錄
圖表 9修改字體樣式
圖表 10警告
為了不出現(xiàn)重復聊天框的BUG,所以要設(shè)置一個警告。
圖表 11繪圖界面
這里只繪制了一個圈和字體,但也可以實現(xiàn)其他的繪畫,比如畫直線等等,但需要在代碼中加入,這里沒有加是因為我覺得這樣設(shè)計會比較好看。
圖表 12繪畫界面彈出
只要點擊來畫畫吧,就會彈出繪畫的這個窗口,這里本來想設(shè)計成后面的那些窗口都消失,但發(fā)現(xiàn)這樣不太明顯,就將那條代碼刪除了。
圖表 13計時器
點擊計時器按鈕,就會跳轉(zhuǎn)到計時器的這個頁面來,點擊開始就能夠開始計時,停止就停止計時,重置就是重新開始。
圖表 14點擊重置后
點擊重置后,時間就歸零了。
3)數(shù)據(jù)庫操作
圖表 15數(shù)據(jù)庫登錄
這里是老師上課講解的內(nèi)容,這里進行了一個結(jié)合,只要點擊右下方的按鈕,就能夠彈出這個頁面,也就是“小蜜蜂數(shù)據(jù)”,接著就能夠鏈接數(shù)據(jù)庫查詢信息了。
圖表 16查詢信息頁面
因為沒有數(shù)據(jù)庫,所以這里用的是老師之前教課時所使用的,自己也嘗試建立數(shù)據(jù)庫,發(fā)現(xiàn)了很多問題,諸如數(shù)據(jù)的問題,要創(chuàng)建ID類但是一直無法設(shè)置好,導致程序出現(xiàn)故障等等。
圖表 17重新建立數(shù)據(jù)庫界面
因為原本數(shù)據(jù)庫不太適合我的聊天軟件,于是進行了更改,這樣就能夠查詢好友的信息,比較匹配我的聊天軟件。
4)TCP網(wǎng)絡(luò)通信
圖表 18同時打開服務端和客戶端
能夠運行服務端和客戶端,界面上的LOGO是我設(shè)計的小蜜蜂。
圖表 19多線程鏈接
兩個客戶端能夠和服務端鏈接并且發(fā)送消息。
圖表 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
;connect(ui
->drawBtn
,&QPushButton
::clicked
,[=](){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,"警告","發(fā)送的內(nèi)容不能為空!");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
;
break;case UserLeft
:stream
>>name
;
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,"警告","保存內(nèi)容不能為空!");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_OBJECT
public: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 (
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,"警告","已有相關(guān)聊天框,請勿重復點擊!");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_OBJECT
public:explicit denglu(QWidget
*parent
= 0);~denglu();private:Ui
::denglu
*ui
;QVector
<bool> IsShow
;
};#endif (
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));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();return;}
}void mServer
::on_btn_discon_clicked()
{mserver
->close();for(int i
=0;i
<list_sock
.length();i
++){list_sock
[i
]->abort(); }list_sock
.clear();exit(0);
}void mServer
::on_btn_sendMsg_clicked()
{QDataStream
out(&mdata
,QIODevice
::WriteOnly
); out
.setVersion(QDataStream
::Qt_5_8
);mtype
=101; QString 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
); out
.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; if(totalsize
< 1){QDataStream
in(sock
);in
.setVersion(QDataStream
::Qt_5_8
);in
>>mtype
; in
>>totalsize
; mdata
.clear(); qDebug()<<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
); out
.setVersion(QDataStream
::Qt_5_8
);QString str
=ui
->lineEdit
->text();QByteArray ba
=str
.toLocal8Bit();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
);
send_data
.clear();}
五、實驗總結(jié)
在本次實踐學習中,我運用上課學習到的知識進行了自己的設(shè)計制作,會發(fā)現(xiàn)當跟著老師的時候會覺得很輕松的事情,自己上手了卻變得困難了,比如多線程這一塊內(nèi)容,跟著老師走的時候就會知道下一步應該走向哪里,但是自己打開的時候卻經(jīng)常報錯,而且因為地址的問題要找很多的資料,反復去回憶老師所講過的內(nèi)容,因為要復制一些程序到源地址中,而這幾個程序我印象不深,所以也導致了在這個問題上面浪費太多時間,這也讓我決定以后類似于這樣的知識點應該記錄到筆記中去。
還有就是手動建槽的時候也要注意規(guī)范,之前因為想測試某個功能,忘記在頭文件中加入槽,等反應過來之后再去添加槽,卻發(fā)現(xiàn)還是運行不了,代碼也找了很多參考,但是都沒有能夠找出問題,所以這一個內(nèi)容我全部刪除重新再打一次代碼,而后就運行成功了,所以我也認識到規(guī)范性也是很重要的。
在最初的UI設(shè)計中我是參考別人的設(shè)計,和同學一起討論設(shè)計出來的,但發(fā)現(xiàn)功能太少了,遠遠不符合要求,所以再翻找以前的學習代碼去找該怎么實現(xiàn)我想要的功能,然后再進行設(shè)計,所以在最初設(shè)計的基礎(chǔ)上做了很多變動,比如因為沒有數(shù)據(jù)庫,所以和我最先設(shè)想的查找好友資料也無法做出來,只能參考原來上課時候的學習代碼進行制作,還有原本想要管理員按鈕連接服務端進行跳轉(zhuǎn),卻發(fā)現(xiàn)服務端需要單獨開設(shè)一個項目,那如何把項目放在另一個項目下面我也是找了很多資料,但也一直無法實現(xiàn),這也是我的一個遺憾,就是無法在一個項目中同時做到多個功能,只能在聊天的基礎(chǔ)上搭載繪畫,計時器,天氣數(shù)據(jù)查詢等的功能。
最后就是代碼,其實我參考學習了很多資料,包括之前上課所講的代碼,我都有做參考,在這個過程中也重新學到了很多知識,也算是查缺補漏了,剛開始覺得這個作業(yè)很難,但后來一步一步一個一個功能慢慢實現(xiàn)之后,就會發(fā)現(xiàn)其實還是能夠完成的,每次遇到難題我都會去請教舍友或者網(wǎng)上搜索資料,一步一步試錯也讓我曾經(jīng)很崩潰,有時候一整天都在完成一個功能,雖然最后結(jié)果出來之后不是很驚艷,但是我覺得我已經(jīng)做到了我的最好,也學習到了很多!
能做出這個軟件,也很感謝:
B站up主:性感的大飛俠-【QT實現(xiàn)群聊聊天系統(tǒng)-嗶哩嗶哩】 https://b23.tv/yrhCLWL
唔國旗u【04_QT_頁面切換(兩個ui界面)-嗶哩嗶哩】 https://b23.tv/wEWbfqW
以上指導很有用!
實驗結(jié)果存在較多BUG,很不完善!歡迎討論!
總結(jié)
以上是生活随笔為你收集整理的Linux系统开发|QT制作聊天软件实验报告的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。