Qt之高仿QQ通信软件(四)
作者:互联网
Qt之高仿QQ通信软件(四)
前言:之前写完了一直没有更新,有部分原因是逻辑混淆、结构不清晰,所以停更了一段时间。这次利用假期时间从头到尾进行修改,不足之处或更好的想法请及时指出,鄙人也是小白哈。
一:界面介绍
修正后的效果图:
由于懒的制作动态GIF视频,所以看不到界面的动态、翻转的效果,有空回头制作放上去。
翻转后的界面:主要对服务器参数配置,进行注册、登录通信
配置完成后自动连接服务器
下面附上翻转代码:
RotatingStackedWidget.h
#ifndef ROTATINGSTACKEDWIDGET_H
#define ROTATINGSTACKEDWIDGET_H
#include <QWidget>
#include <QVariant>
#include <QStackedWidget>
class RotatingStackedWidget : public QStackedWidget
{
Q_OBJECT
Q_PROPERTY( float rotateVal READ rotateVal WRITE setRotateVal)
public:
/**
* @brief RotatingStackedWidget 构造函数
* @param parent
*/
explicit RotatingStackedWidget(QWidget *parent = 0);
~RotatingStackedWidget();
/**
* @brief paintEvent 绘制事件
*/
void paintEvent(QPaintEvent *event);
public slots:
/**
* @brief nextPage 下一页
*/
void nextPage();
public:
/**
* @brief rotate index 跳转到索引页
*/
void rotate(int index);
/**
* @brief rotateVal 旋转值
* @return
*/
float rotateVal();
/**
* @brief setRotateVal 设置旋转值
* @param fl 值
*/
void setRotateVal(float fl);
private slots:
/**
* @brief valChanged 旋转值改变了
*/
void valChanged(QVariant);
/**
* @brief animDone 动画结束
*/
void animDone();
private:
/**
* @brief iRotateVal 旋转值
*/
float iRotateVal;
/**
* @brief isAnimating 旋转动画中
*/
bool isAnimating;
/**
* @brief nextIndex 下一个索引页
*/
int nextIndex;
};
#endif // ROTATINGSTACKEDWIDGET_H
RotatingStackedWidget.cpp
#include "rotatingstackedwidget.h"
#include <QVariant>
#include <QLabel>
#include <QPropertyAnimation>
#include <QPainter>
#include <QParallelAnimationGroup>
#include <QTransform>
RotatingStackedWidget::RotatingStackedWidget(QWidget *parent) :
QStackedWidget(parent)
{
iRotateVal = 0;
isAnimating = false;
setAttribute(Qt::WA_TranslucentBackground, true);
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
}
RotatingStackedWidget::~RotatingStackedWidget()
{
}
/**
* @brief RotatingStackedWidget::paintEvent
* 绘制
* @param event
*/
void RotatingStackedWidget::paintEvent(QPaintEvent *event)
{
if (isAnimating)
{
if (iRotateVal > 90)
{
QPixmap pixmap(widget(nextIndex)->size());
widget(nextIndex)->render(&pixmap);
QPainter painter(this);
QTransform transform;
transform.translate(width() / 2, 0);
transform.rotate(iRotateVal + 180, Qt::YAxis);
painter.setTransform(transform);
painter.drawPixmap(-1 * width() / 2, 0, pixmap);
}
else
{
QPixmap pixmap(currentWidget()->size());
currentWidget()->render(&pixmap);
QPainter painter(this);
QTransform transform;
transform.translate(width() / 2, 0);
transform.rotate(iRotateVal, Qt::YAxis);
painter.setTransform(transform);
painter.drawPixmap(-1 * width() / 2, 0, pixmap);
}
}
else {
QWidget::paintEvent(event);
}
}
/**
* @brief RotatingStackedWidget::nextPage
* 下一个page
*/
void RotatingStackedWidget::nextPage()
{
rotate((currentIndex() + 1) >= count() ? 0 : (currentIndex() + 1));
}
/**
* @brief RotatingStackedWidget::rotate
* 执行翻转
* @param index
*/
void RotatingStackedWidget::rotate(int index)
{
if(isAnimating) return;
nextIndex = index;
int offsetx=frameRect().width();
int offsety=frameRect().height();
widget(index)->setGeometry ( 0, 0, offsetx, offsety );
QPropertyAnimation *animnow = new QPropertyAnimation(this,"rotateVal");
animnow->setDuration(500);
animnow->setEasingCurve(QEasingCurve::Linear);
animnow->setStartValue(0);
animnow->setEndValue(180);
connect(animnow, SIGNAL(valueChanged(QVariant)), this, SLOT(valChanged(QVariant)));
connect(animnow, SIGNAL(finished()), this, SLOT(animDone()));
currentWidget()->hide();
isAnimating = true;
animnow->start();
}
/**
* @brief RotatingStackedWidget::rotateVal
* @return
*/
float RotatingStackedWidget::rotateVal()
{
return iRotateVal;
}
/**
* @brief RotatingStackedWidget::setRotateVal
* @param fl
*/
void RotatingStackedWidget::setRotateVal(float fl)
{
iRotateVal = fl;
}
void RotatingStackedWidget::valChanged(QVariant)
{
repaint();
}
/**
* @brief RotatingStackedWidget::animDone
*
*/
void RotatingStackedWidget::animDone()
{
iRotateVal = 0;
isAnimating = false;
widget(nextIndex)->show();
widget(nextIndex)->raise();;
setCurrentWidget(widget(nextIndex));
repaint();
}
界面用QWidget窗口显示,提升为RotatingStackedWidget
界面切换void nextPage();
二、连接服务器,使用JSON通信
/**@
*连接服务器后需要进行的操作
*1、注册
-
用JSON包装注册信息向服务器发送(JSON包装的“type”类型来判断发送的什么类型信息,注册信息、登录信息、好友聊天信息、群聊信息、上下线信息等
-
服务器接收到注册信息后返回注册成功或失败信息
-
对服务器返回的注册信息进行解析
*/
使用JSON发送数据和接收数据非常方便,这也是前期没学过导致后面非常的繁琐原因之一。
简单介绍一下本程序JSON的发送数据的用法:
//注册消息发送到服务器
void Log_tabel::SendMsg_to_Server()
{
if(!ui->UserEdit->text().isEmpty() && !ui->PasswordEdit->text().isEmpty())
{
Mycpp::USERNAME = ui->UserEdit->text();
Mycpp::USERPASS = ui->PasswordEdit->text();
//生成JSON
QJsonObject userinfo_json;
QJsonObject data;
data.insert("username" , Mycpp::USERNAME);
data.insert("userpass" , Mycpp::USERPASS);
data.insert("userid",Mycpp::USERID);
data.insert("text","");
userinfo_json.insert("data",QJsonValue(data));
userinfo_json.insert("from_id" , Mycpp::USERID);
userinfo_json.insert("type",USER_REGIN);
QJsonDocument document;
document.setObject(userinfo_json);
QByteArray bytearray = document.toJson(QJsonDocument::Compact);
QString strjson(bytearray);
qDebug()<<strjson;
//发送JSON
write_socket->write(bytearray);
QMessageBox::information(this,QStringLiteral("发送注册信息"),QStringLiteral("发送成功"));
}
else
{
qDebug()<<"用户名或密码不能为空";
QMessageBox::information(this,QStringLiteral("发送注册信息"),QStringLiteral("发送失败"));
}
}
服务器对注册信息进行解析
//解析用户注册的个人信息
void MainWindow::M_USER_REGIN(QJsonValue &dataVal,QTcpSocket *Writ_Read_socket)
{
// data 的 value 是对象
if (dataVal.isObject())
{
QJsonObject dataObj = dataVal.toObject();
QString strName = dataObj.value("username").toString();
QString strPwd = dataObj.value("userpass").toString();
USER_ID = dataObj.value("userid").toInt();
QJsonObject json;
//用户名没注册过
if(!isReg_Username(strName))
{
// 返回客户端
qDebug()<<"没注册GUO";
USER_ID = ++ClIENT_COUNT;//分配ID
QJsonObject data_object;
data_object.insert("id", USER_ID);
data_object.insert("name", strName);
data_object.insert("passwd", strPwd);
data_object.insert("text","");
json.insert("data",data_object);
json.insert("type",USER_REGIN_SUCCESS);
// 构建 Json 文档
QJsonDocument document;
document.setObject(json);
Writ_Read_socket->write(document.toJson(QJsonDocument::Compact));
Save_Userinfo_database(USER_ID,strName,strPwd);//保存到数据库
}
else
{
qDebug()<<"注册过";
QJsonObject data_object;
data_object.insert("id", USER_ID);
data_object.insert("name", strName);
data_object.insert("passwd", strPwd);
data_object.insert("text","");
json.insert("data",data_object);
json.insert("type",USER_REGIN_NO);
// 构建 Json 文档
QJsonDocument document;
document.setObject(json);
Writ_Read_socket->write(document.toJson(QJsonDocument::Compact));
}
USER_ID = -1;
}
}
信息类型自定义
typedef enum{
USER_REGIN = 0x01, //用户注册发送的个人信息
USER_REGIN_SUCCESS, //返回注册成功信息
USER_REGIN_NO , //返回注册失败信息
USER_CHAR_MSG , //用户发送聊天信息
USER_LOGIN , //用户登录信息
USER_LOGIN_SUCCESS, //返回登录成功信息
USER_LOGIN_NO , //返回登录失败信息
}E_INFO;
还有连接或断开信号关联操作就不一一介绍了。
三、服务器进行验证登录信息
通过账号密码的输入框数据包装JSON发送到服务器进行验证
同样服务器返回验证成功或失败的信息,验证通过后进入主界面
后续:主界面的效果图和主界面的用法在单独介绍了。
标签:QQ,Qt,RotatingStackedWidget,void,brief,通信软件,USER,iRotateVal,include 来源: https://blog.csdn.net/qq_46495964/article/details/113379563