目录
denglu.cpp、main.cpp、widget.cpp
一、界面展示(界面用ui 设计)
群成员展示界面( denglu)
聊天界面展示( widget )
二、代码展示 (所有代码非原创)
denglu.h和widget.h
#ifndef DENGLU_H
#define DENGLU_H
#include <QWidget>
namespace Ui {
class denglu;
}
class denglu : public QWidget
{
Q_OBJECT
public:
explicit denglu(QWidget *parent = nullptr);
~denglu();
private:
Ui::denglu *ui;
QVector<bool> IsShow;
};
#endif // DENGLU_H
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QUdpSocket>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent,QString name);
//重写关闭事件
void closeEvent(QCloseEvent *);
enum Msgtype{Msg,UserEnter,UserLeft};//枚举 分别代表 普通信息 用户进入 用户离开
void sndMsg(Msgtype type);//广播udp信息
QString getName();//获取名字
QString getMsg();//获取聊天信息
void userEnter(QString username);//处理用户进入
void userLeft(QString username,QString time);//处理用户离开
void ReceiveMessage(); //接受UDP消息
~Widget();
signals:
void closeWidget();
private:
Ui::Widget *ui;
QString myname;
quint16 port;//端口
QUdpSocket *udpSocket;//udp 套接字
};
#endif // WIDGET_H
denglu.cpp、main.cpp、widget.cpp
#include "denglu.h"
#include "ui_denglu.h"
#include<QIcon>
#include<QToolButton>
#include"widget.h"
#include<QMessageBox>
denglu::denglu(QWidget *parent) :
QWidget(parent),
ui(new Ui::denglu)
{
ui->setupUi(this);
//设置图标
//路径: 冒号+前缀+路径
this->setWindowIcon(QIcon(":/imagine/qq.jpg"));
//设置名称
this->setWindowTitle("qq 2022");
QList<QString> nameList;
nameList<<"泼猴"<<"哪吒"<<"菩萨"<<"玉帝老2"<<"如来老6"<<"师傅"<<"偷吃人参果"<<"沙僧"<<"小白";
QStringList iconNameList; //图标资源列表
iconNameList << "1"<< "2" <<"3" <<"4"<< "5"<<"6"<<"7"<<"8"<<"9";
QVector< QToolButton *> vector;
for(int i=0;i<9;i++)
{
QToolButton *btn=new QToolButton(this);
//加载图标
btn->setIcon(QPixmap(QString(":/imagine/%1.jpg").arg(iconNameList[i])));
//设置图片大小
btn->setIconSize(QPixmap(QString(":/imagine/%1.jpg").arg(iconNameList[i])).size());
//设置网名
btn->setText(QString("%1").arg(nameList[i]));
//设置为透明
btn->setAutoRaise(true);
//设置显示格式
btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
//放到vlayout布局中
ui->vlayout->addWidget(btn);
vector.push_back(btn);
IsShow.push_back(false);
}
for(int i=0;i<9;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();
//关闭时将对应的IsShow变为false;
connect(widget,&Widget::closeWidget,this,[=](){
IsShow[i]=false;
});
});
}
}
denglu::~denglu()
{
delete ui;
}
#include "widget.h"
#include <QApplication>
#include"denglu.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//Widget w;
//w.show();
denglu b;
b.show();
return a.exec();
}
#include "widget.h"
#include "ui_widget.h"
#include<QDataStream>
#include<QMessageBox>
#include<QDateTime>
#include<QComboBox>
#include<QColorDialog>
#include<QFileDialog>
Widget::Widget(QWidget *parent ,QString name) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
myname=name;
this->port=9999;
this->udpSocket=new QUdpSocket(this);
udpSocket->bind(port,QUdpSocket::ShareAddress |QUdpSocket::ReuseAddressHint);
//
connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::ReceiveMessage);
//连接发送按钮
connect(ui->sendBtn,&QPushButton::clicked,[=](){
sndMsg(Msg);
});
//新用户进入
sndMsg(UserEnter);
connect(ui->exitBtn,&QPushButton::clicked,[=](){
this->close();
});
//字体类型
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,[=](bool checked){
if(checked)
{
ui->msgTxtEdit->setFontWeight(QFont::Bold);
}
else {
ui->msgTxtEdit->setFontWeight(QFont::Normal);
}
});
//字体倾斜
connect(ui->italicTbtn,&QToolButton::clicked,[=](bool checked){
ui->msgTxtEdit->setFontItalic(checked);
ui->msgTxtEdit->setFocus();
});
//字体下划线
connect(ui->underlineTBtn,&QToolButton::clicked,[=](bool checked){
ui->msgTxtEdit->setFontUnderline(checked);
ui->msgTxtEdit->setFocus();
});
//清空功能
connect(ui->clearTBtn,&QToolButton::clicked,[=](){
ui->msgBrowser->clear();
});
connect(ui->colorTBtn,&QToolButton::clicked,[=](){
QColor color=QColorDialog::getColor(color,this);
ui->msgTxtEdit->setTextColor(color);
});
connect(ui->saveTBtn,&QToolButton::clicked,[=](){
if(ui->msgBrowser->toPlainText().isEmpty())
{
QMessageBox::warning(this,"警告","警告!保存内容不能为空!");
return;
}
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 *e) //重写离开事件
{
emit this->closeWidget();
sndMsg(UserLeft);
udpSocket->close();
udpSocket->destroyed();
QWidget::closeEvent(e);
}
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::userEnter(QString username) //处理用户进入
{
bool IsEmpty=ui->tableWidget->findItems(username,Qt::MatchExactly).isEmpty();
if(IsEmpty)
{
QTableWidgetItem *table=new QTableWidgetItem(username);
ui->tableWidget->insertRow(0);
ui->tableWidget->setItem(0,0,table);
ui->msgBrowser->setTextColor(QColor(Qt::gray));
ui->msgBrowser->append(username+"已上线");
ui->userNumLbl->setText(QString("在线人数:%1").arg(ui->tableWidget->rowCount()));
sndMsg(UserEnter);
}
}
void Widget::userLeft(QString username, QString time) //处理用户离开
{
bool IsEmpty=ui->tableWidget->findItems(username,Qt::MatchExactly).isEmpty();
if(!IsEmpty)
{
int row=ui->tableWidget->findItems(username,Qt::MatchExactly).first()->row();
ui->tableWidget->removeRow(row);
ui->msgBrowser->append(QString("%1用户于%2离开").arg(username).arg(time));
ui->userNumLbl->setText(QString("在线人数:%1").arg(ui->tableWidget->rowCount()));
}
}
void Widget::ReceiveMessage() //接收udp消息
{
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->append("["+name+"]"+time);
ui->msgBrowser->append(msg);
break;
case UserLeft:
stream>>name;
userLeft(name,time);
break;
case UserEnter:
stream>>name;
userEnter(name);
break;
}
}
Widget::~Widget()
{
delete ui;
}
注意:群成员用户界面的用户头像需要自己建立一个资源文件夹保存。方法如下
三、软件制作
选择Release构建(平常我们检查功能是否实现,是默认Debug构建),这样构建出来的 .exe 比Debug构建的小
下面所有图片中的 .exe 都是新建的文件夹下的 .exe
这样一个软件就诞生了。但是新生成的这个 .exe 只能在本机上运行,如果想要能将这个软件传输给其他人,就需要使用 Enigma Virtual Box 这个打包工具。
这样一款可传输的pc端的软件就诞生了,只是没有图标。哈哈哈哈哈。自己努力做出来的软件没有图标也一样nice。 如果需要图标的,可以在网上搜索怎样添加图标。
完美!!!!!!!!!!!!!!!!!!
本文含有隐藏内容,请 开通VIP 后查看