其他分享
首页 > 其他分享> > Qt之高仿QQ通信软件(四)

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的发送数据的用法:

//注册消息发送到服务器
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