qqwidget.cpp
#include "qqwidget.h"
#include "ui_qqwidget.h"
qqwidget::qqwidget(QWidget *parent,QString name) :
QWidget(parent),
ui(new Ui::qqwidget)
{
ui->setupUi(this);
//建立udp监听套接字
udpsocket=new QUdpSocket(this);
usName=name;
port=9999;
//绑定端口和地址 模式:共享地址,断线重连才能构成广播群发
udpsocket->bind(port,QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint);
sendMsg(UserEnter);
//发送消息
connect(ui->ButtonSend,&QPushButton::clicked,[=](){
sendMsg(Msg);
});
//接收消息
connect(udpsocket,&QUdpSocket::readyRead,[=](){
reciveMsg();
});
//换字体
connect(ui->fontComboBox,&QFontComboBox::currentFontChanged,[=](const QFont&font){
ui->messageTextEdit->setCurrentFont(font);
ui->messageTextEdit->setFocus();
});
//调节字体大小
void (QComboBox::*func)(const QString&text)=&QComboBox::currentIndexChanged;//遇到信号重载,用函数指针处理一下
connect(ui->comboBox,func,[=](const QString &text){
ui->messageTextEdit->setFontPointSize(text.toInt());
ui->messageTextEdit->setFocus();
});
//字体加粗
connect(ui->toolButton_B,&QToolButton::clicked,[=](bool ischecked){
if(ischecked)
{
ui->messageTextEdit->setFontWeight(QFont::Bold);
ui->messageTextEdit->setFocus();
}
else
{
ui->messageTextEdit->setFontWeight(QFont::Normal);
ui->messageTextEdit->setFocus();
}
});
//斜体字
connect(ui->toolButton_I,&QToolButton::clicked,[=](bool isChecked){
ui->messageTextEdit->setFontItalic(isChecked);
});
//下划线字体
connect(ui->toolButton_U,&QToolButton::clicked,[=](bool isChecked){
ui->messageTextEdit->setFontUnderline(isChecked);
});
//字体颜色
connect(ui->toolButton_Color,&QToolButton::clicked,[=](){
QColor color = QColorDialog::getColor(Qt::red);//会话窗口,得到默认颜色
ui->messageTextEdit->setTextColor(color);
});
//清除聊天框
connect(ui->toolButton_Clear,&QToolButton::clicked,[=](){
ui->Textdisplay->clear();
});
//保存聊天记录
connect(ui->toolButton_Download,&QToolButton::clicked,[=](){
QString path=QFileDialog::getSaveFileName(this,"存储位置","聊天记录","*.txt");
QFile file(path);
file.open(QIODevice::WriteOnly);
QTextStream stream(&file);
stream<<ui->Textdisplay->toPlainText();
file.close();
});
}
void qqwidget::sendMsg(qqwidget::msgType type)
{//发送消息
QByteArray data;
//数据流,以空格?/\0结束?
QDataStream stream(&data,QIODevice::WriteOnly);
stream<<type<<getUserName();
//判断编辑框是否为空
if(!ui->messageTextEdit->toPlainText().isEmpty())
stream<<getEditMsg();
//发送消息流
udpsocket->writeDatagram(data,QHostAddress::Broadcast,port);
}
void qqwidget::reciveMsg()
{//接收消息
//接收消息大小
qint64 size = udpsocket->pendingDatagramSize();
//定义qbytearray类型数据大小
QByteArray data=QByteArray(size,0);
//读取接收消息
udpsocket->readDatagram(data.data(),size);
//以只读方式写入到data中
QDataStream stream(&data,QIODevice::ReadOnly);
int MsgType;
stream>>MsgType;//接收第一段消息,类型
QString username;
QString getmsg;
//时间
QString time=QDateTime::currentDateTime().toString("yyyy-MM-dd hh-mm-ss");
switch (MsgType)
{
case Msg://消息
stream>>username>>getmsg;
ui->Textdisplay->setTextColor(Qt::blue);
ui->Textdisplay->append("["+username+"]"+time);
ui->Textdisplay->append(getmsg);
break;
case UserEnter://用户进入
stream>>username;
userEnter(username);
break;
case UserLeave://用户离开
stream>>username;
userLeave(username,time);
break;
}
}
void qqwidget::userEnter(QString username)
{//用户进入
bool isEmpty=ui->OnlineMember->findItems(username,Qt::MatchExactly).isEmpty();
//判断在tablewidget中是否存在
if(isEmpty)
{
QTableWidgetItem*item=new QTableWidgetItem(username);
ui->OnlineMember->insertRow(0);
ui->OnlineMember->setItem(0,0,item);
//QString time=QDateTime::currentDateTime().toString(QString("yyyy-MM-dd hh-mm-ss"));
ui->Textdisplay->setTextColor(Qt::gray);
ui->Textdisplay->append(QString("%1进入群聊").arg(username));
//更改在线人数
ui->numberCount->setText(QString("在线用户人数:%1").arg(ui->OnlineMember->rowCount()));
sendMsg(UserEnter);//进入群聊的人,需要向外广播进入消息
}
}
void qqwidget::userLeave(QString username,QString time)
{//用户离开
bool isEmpty=ui->OnlineMember->findItems(username,Qt::MatchExactly).isEmpty();
if(!isEmpty)
{
int row=ui->OnlineMember->findItems(username,Qt::MatchExactly).first()->row();
ui->OnlineMember->removeRow(row);
ui->Textdisplay->setTextColor(Qt::gray);
ui->Textdisplay->append(QString("%1离开群聊%2").arg(username).arg(time));
ui->numberCount->setText(QString("在线用户人数:%1").arg(ui->OnlineMember->rowCount()));
}
}
QString qqwidget::getEditMsg()
{//得到编辑信息
QString data = ui->messageTextEdit->toHtml();
ui->messageTextEdit->clear();
ui->messageTextEdit->setFocus();
return data;
}
QString qqwidget::getUserName()
{//得到用户姓名
return usName;
}
void qqwidget::closeEvent(QCloseEvent *event)
{
emit this->closeWidget();
sendMsg(UserLeave);//用户离开广播消息
udpsocket->close();
udpsocket->destroyed();
QWidget::closeEvent(event);
}
qqwidget::~qqwidget()
{
delete ui;
}
dialoglist.cpp
#include "dialoglist.h"
#include "ui_dialoglist.h"
Dialoglist::Dialoglist(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Dialoglist)
{
ui->setupUi(this);
//创建窗口名称
this->setWindowTitle("QQ2020");
//创建窗口图标
this->setWindowIcon(QPixmap(":/images/qq.png"));
//创建成员列表
QList<QString> namelist;
namelist<<"小何同学"<<"小罗同学"<<"小夏同学"<<"小张同学"<<"小美同学"<<"小高同学"<<"小李同学"<<"小飞同学"<<"小王同学";
for(int i{0};i<9;++i)
{//创建工具按钮,建立每个在线成员
QToolButton*btn=new QToolButton;
btn->setText(namelist[i]);
btn->setIcon(QPixmap(":/images/qq.png"));
btn->setIconSize(QPixmap(":/images/qq.png").size()/1.5);
btn->setAutoRaise(true);
btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
ui->mylayout->addWidget(btn);//加入到布局中
vToolList.push_back(btn);//将成员放入容器中
isShow.push_back(false);//未打开会话窗口的标记为false
}
for(int i{0};i<9;++i)
{//打开会话窗口
connect(vToolList[i],&QToolButton::clicked,[=](){
if(isShow[i])//如果已经打开return
return;
qqwidget*newWidget=new qqwidget(nullptr,vToolList[i]->text());
newWidget->setWindowTitle(vToolList[i]->text());
newWidget->setWindowIcon(vToolList[i]->icon());
newWidget->show();//显示会话窗口
isShow[i]=true;//打开的标记为true
connect(newWidget,&qqwidget::closeWidget,[=](){//会话窗口关闭触发closewideget信号,窗口状态标记为false
isShow[i]=false;
});
});
}
}
Dialoglist::~Dialoglist()
{
delete ui;
}
//头文件dialoglist.h
#ifndef DIALOGLIST_H
#define DIALOGLIST_H
#include <QWidget>
#include <QToolButton>
#include <QList>
#include <qqwidget.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Dialoglist; }
QT_END_NAMESPACE
class Dialoglist : public QWidget
{
Q_OBJECT
public:
Dialoglist(QWidget *parent = nullptr);
~Dialoglist();
private:
Ui::Dialoglist *ui;
QVector<QToolButton*>vToolList;
QVector<bool>isShow;
};
#endif // DIALOGLIST_H
头文件qqwidget.h
#ifndef QQWIDGET_H
#define QQWIDGET_H
#include <QWidget>
#include <QUdpSocket>
#include <QDateTime>
#include <QTableWidgetItem>
#include <QDebug>
#include <QDataStream>
#include <QColorDialog>
#include <QFile>
#include <QFileDialog>
namespace Ui {
class qqwidget;
}
class qqwidget : public QWidget
{
Q_OBJECT
enum msgType{Msg,UserEnter,UserLeave};
public:
explicit qqwidget(QWidget *parent = nullptr,QString name="");
~qqwidget()override;
//窗口关闭事件
void closeEvent(QCloseEvent *event) override;
//发送消息
void sendMsg(msgType type);
//接受消息
void reciveMsg();
//得到用户名字
QString getUserName();
//得到编辑框信息
QString getEditMsg();
//用户进入操作
void userEnter(QString username);
//用户离开操作
void userLeave(QString username,QString time);
private:
Ui::qqwidget *ui;
QString usName;
quint16 port;
QUdpSocket*udpsocket{nullptr};
signals:
void closeWidget();
};
#endif // QQWIDGET_H