QT网络聊天室(udp)
1.第一部分界面部分
第一部分的QT(QQ)界面部分的控件分别有登录是一个button类用于发送登录信息
lineEdit类用于接收用户名,还有一些装饰的小控件具体请看UI文件
首先1.我们实现了一个根据鼠标滑动可以拖动主窗口的功能
二。第二部分窗口滑动事件
使用鼠标拖动事件与鼠标按压事件的一个交互请注意这里的按压点应该减去我们的鼠标中心点达到一个拖动窗口而不更换窗口位子的现象
用到了
QMouseEvent Qpoint 类分别用于处理鼠标事件和得到一个坐标点
在这里插入代码片
void Widget::mousePressEvent(QMouseEvent *event)
{
#if 0
qDebug() << event->pos();//鼠标在窗体上的坐标,窗体的坐标原点在窗体的左上角
qDebug() << event->globalPos();//鼠标相对于屏幕坐标系的坐标
qDebug() << this->pos();//窗体在屏幕上面的坐标
#endif
mousePressPoint = event->pos();
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
#if 0
qDebug() << event->pos();//鼠标在窗体上的坐标,窗体的坐标原点在窗体的左上角
qDebug() << event->globalPos();//鼠标相对于屏幕坐标系的坐标
qDebug() << this->pos();//窗体在屏幕上面的坐标
#endif
this->move(event->globalPos() - mousePressPoint);
}
三。UDP按钮发送部分
既然是UDP通信在QT中自然有与之相关的类如 QUdpSocket创建一个套接字用于udp通信我们在开始用Qudosocket创建对象后通过连接botton 的槽函数用json包的形式发送json数据包首先定义为一个json对象插入数据后在装换为jsondcument对象再用tojson()函数转换为QArray数组对象
//登录界面的槽函数
void Widget::on_pushButton_clicked()
{
chatWindow->setUsername(ui->lineEdit->text());
chatWindow->show();
broadcastLoginMessage();
this->close();
}
//发送json包的函数用udpdatawrite函数写入数据
void Widget::broadcastLoginMessage()
{
QJsonObject jsonObject;
jsonObject.insert("message_type",1);
jsonObject.insert("name",ui->lineEdit->text());
jsonObject.insert("content","I am login");
//jsonObject.insert("port",8888);//聊天界面的套接字端口号
jsonObject["port"] = 8888;
//将jsonObject转成json格式的数据
QJsonDocument jsondoc(jsonObject);
QByteArray jsonData = jsondoc.toJson();
udpSocket->writeDatagram(jsonData,QHostAddress(QHostAddress::Broadcast),8888);
}
登录端主函数结束
第四部分第二窗口收端
首先我们要在收做的是创建一个Qudpsocket对象用bild函数绑定自己的端口并且连接一个信号,当有人给我发包的时候系统自动调用recvread函数从而进入下一个阶段
在这里插入代码片
destIP = "255.255.255.0";
destport=8888;
udpSocket = new QUdpSocket(this);
bool ok = udpSocket->bind(8888);
if(!ok){
qDebug() << "Fail to bind port:8888 , error:" << udpSocket->errorString();
return;
}
connect(udpSocket,SIGNAL(readyRead()),this,SLOT(recvMessage()));
}
第五部分接受函数在一个循环体中使用readData函数将刚才发送的函数进来接受并交给一个函数出统一处理
void ChatWindow::recvMessage()
{
//读取数据
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram(datagram.data(), datagram.size(),
&sender, &senderPort);
//接受到信号后将进去转换json函数中之中我们传入我们的数据,IP地址 端口号
processTheDatagram(datagram,sender,senderPort);
}
return;
}
第六部分在处理函数中解析并根据发数据包的不同来作用于不同的功能刚开始的值为1直接跳入来listwiget中发广播包
void ChatWindow::processTheDatagram(const QByteArray &data,const QHostAddress &sender,
const int senderPort)
{
//将我们的接收到的json包借读根据不同的message_type值来选择相应的类容
QJsonParseError parseError;
qDebug()<<senderPort;
QJsonDocument jsondoc = QJsonDocument::fromJson(data,&parseError);
if(jsondoc.isNull() || parseError.error != QJsonParseError::NoError){
qDebug() << "Fail to parse json data : " << parseError.errorString();
return;
}
QJsonObject jsonObject = jsondoc.object();
int message_type = jsonObject["message_type"].toInt();
QString name = jsonObject["name"].toString();
QString content = jsonObject["content"].toString();
short port = (short)jsonObject["port"].toInt();
switch(message_type){
case ChatWindow::LOGIN_MESSAGE:
//添加登陆的用户到好友列表
//给登陆的用户发送一个应答消息,告诉他自己在线
doUserLogin(QHostAddress(sender.toIPv4Address()),name,port);
break;
case ChatWindow::CHAT_MESSAGE:
//显示聊天的消息
break;
case ChatWindow::ACK_MESSAGE:
//添加应答用户到好友列表
doUserAck(QHostAddress(sender.toIPv4Address()),name,port);
return;
case ChatWindow::QUIT_MESSAGE:
//将退出的用户从好友列表中删除
doUserQuit(QHostAddress(sender.toIPv4Address()),name,port);
break;
}
displaySendChatMessage(username,content);
return;
}
第七部没法来一个包就将自己的信息加入列表中,加一判断,如果是自己的则不用,如果不是则告诉其他用户
void ChatWindow::addUserToList(const QHostAddress &ip, const QString &name, short port)
{
QString text = QString("%1\n%2:%3").arg(name).arg(ip.toString()).arg(port);
//一种输出文本格式可以相当于printf
ui->listWidget->addItem(new QListWidgetItem(QIcon(":/image/HeadImage.png"),text));
//加图片在listWidget中去
ui->listWidget->setIconSize(QSize(50,50));
//设置图片的大小
return;
//实现了将list上加一个元素
}
//将我们
void ChatWindow::tellLoginUser(const QHostAddress &destIp,const short destPort)
{ //不是自己发的包就要给所有人发一个告知包我上线了
QJsonObject jsonObject;
jsonObject.insert("message_type",ChatWindow::ACK_MESSAGE);
//发送应答型号之后跳到应答函数里面
jsonObject.insert("name",username);
jsonObject["port"] = 8888;
//将jsonObject转成json格式的数据
QJsonDocument jsondoc(jsonObject);
QByteArray jsonData = jsondoc.toJson();
udpSocket->writeDatagram(jsonData,destIp,destPort);
}
//判断自己是不是
bool ChatWindow::checkSelfIp(const QHostAddress &ip)
{
//判断是否是自己在登陆发送的广播消息
QString hostName = QHostInfo::localHostName();
//使用localHostname获取自己当前的本地IP地址,并保存在hostName中
QHostInfo hostInfo = QHostInfo::fromName(hostName);
//将QHstInfo对象使用fromName函数保存一个键值对
QList<QHostAddress> addressList = hostInfo.addresses();
//将创咋好一个QHostaddtess的元素 等于 hostInFo.addresses.
//保存了所有的主机地址
for(int i = 0;i < addressList.size();i ++){
if(addressList[i] == ip){
return true;//遍历
}
}
return false;
}
第八部分 将退出的好友删除利用Qlist类将我们的链表中判断是否有相同的值
void ChatWindow::doUserQuit(const QHostAddress &ip, const QString &name, short port)
{
QString text = QString("%1\n%2:%3").arg(name).arg(ip.toString()).arg(port);
QList<QListWidgetItem *> itemList = ui->listWidget->findItems(text,Qt::MatchExactly);
for(int i = 0;i < itemList.size();i ++){
ui->listWidget->removeItemWidget(itemList[i]);
delete itemList[i];
}
return;
}
第九步再将自己的发送的信息给发出来
void ChatWindow::displaySendChatMessage(const QString &name, const QString &content)
{
QTime time = QTime::currentTime();
QString timeString = time.toString("hh:mm:ss");
QString html = QString(
"<br align = \"right\">"
"<h3 align = \"right\"><font face=\"verdana\" color=\"red\">%1 %2</font></h3>"
"<p align = \"right\"><font size=\"4\" color=\"red\"> %3</p>"
).arg(name).arg(timeString).arg(content);
ui->dis->insertHtml(html);
}
//显示函数 将自己的名字和数据打印出来
void ChatWindow::displayRecvChatMessage(const QString &name, const QString &content)
{
QTime time = QTime::currentTime();
QString timeString = time.toString("hh:mm:ss");
QString html = QString(
"<br align = \"left\">"
"<h3 align = \"left\"><font face=\"verdana\" color=\"red\">%1 %2</font></h3>"
"<p align = \"left\"><font size=\"4\" color=\"blue\"> %3</p>"
).arg(name).arg(timeString).arg(content);
ui->dis->insertHtml(html);
}
第十步显示我们的发送的json聊天语句
void ChatWindow::displaySendChatMessage(const QString &name, const QString &content)
{
QTime time = QTime::currentTime();
QString timeString = time.toString("hh:mm:ss");
QString html = QString(
"<br align = \"right\">"
"<h3 align = \"right\"><font face=\"verdana\" color=\"red\">%1 %2</font></h3>"
"<p align = \"right\"><font size=\"4\" color=\"red\"> %3</p>"
).arg(name).arg(timeString).arg(content);
ui->dis->insertHtml(html);
}
//显示函数 将自己的名字和数据打印出来
void ChatWindow::displayRecvChatMessage(const QString &name, const QString &content)
{
QTime time = QTime::currentTime();
QString timeString = time.toString("hh:mm:ss");
QString html = QString(
"<br align = \"left\">"
"<h3 align = \"left\"><font face=\"verdana\" color=\"red\">%1 %2</font></h3>"
"<p align = \"left\"><font size=\"4\" color=\"blue\"> %3</p>"
).arg(name).arg(timeString).arg(content);
ui->dis->insertHtml(html);
}