基于linux+windows Qt+Mysql 开发的在线答题系统

目录

一 项目描述

二 段位介绍

三 效果展示

四 服务器代码

1.common.h

2.db.h(数据库类)

3.myserver(处理客户端事件)

4.Tcpserver(监听)

5.Tcpsocket(与客户端通信)

6.Thread.h(线程池)

7.User.h(用户类)

main.cpp

db.cpp

myserver.cpp

Tcpserver.cpp

Tcpsocket.cpp

Thread.cpp

User.cpp

五 客户端代码展示

brainstorm.h(具体功能)

communicate.h(通讯)

login.h

register.h

brainstorm.cpp

communicate.cpp

login.cpp

main.cpp

register.cpp

七 界面展示

​编辑


一 项目描述

1、该项目采用C/S结构基于TCP/IP协议,运用Libevent网络库和线程池进行搭建服务器框架。在传输数据中采用Json进行轻量级的数据格式转换。使用spdlog日志库来记录操作信息、出错信息和提醒消息。

2、使用MySQL数据库来存储注册账号信息(段位,分数,名字,密码等),创建一个数据库专门用于存储题目

3、单人训练模式:从mysql题库中随机抽取5道题目进行答题,答对继续作答,答错退出答题界面,最后计算的分

4、答题时间设置为10秒,超过答题时间记作答题错误,最终得分以每题计20分进行统计

5、排位系统:设置用户段位星级登记,只有在上下偏差5颗星的范围内才会匹配成功,如果没有匹配成功,进入到等待队列。有匹配成功的,则将玩家移除等待队列进行答题比赛,答题结束后比较玩家得分情况进行段位改动,并将新的段位记录在数据库中

二 段位介绍

共计段位  
青铜3 1星    到   星耀1  5颗星


青铜3个段位1--3    每个段位3颗星   9
白银3个段位1--3    每个段位3颖星   9


黄金4个段位1-—4    每个段位4颗星   16
铂金4个段位1--4    每个段位4颖星   16


钻石5个段位1--5    每个段位5颗星   25
星耀5个段位1--5    每个段位5颗星   25


三 效果展示

Brainstorm

四 服务器代码

1.common.h

#ifndef COMMOM_H
#define COMMON_H

//用户操作指令
#define OK                  5000
#define REGISTER            5001
#define LOGIN               5002
#define SINGLE_GETQUESTION  5003    //个人训练获取题目
#define RANK                5004    //进行排位赛
#define ANSWER              5005    //发送自己得分返回对手的  排位回答一个问题
#define RANKRESULT          5006    //答题结果发送给服务器  rank结束   

// 错误
#define ERROR     8001   //未知错误
#define USEREXIST 8002   //用户已经存在
#define  NAMEORPASSWD 8003//用户名或者密码错误
#define USERLOGIN 8004   //用户已经存在


#define QUESTION_NUM 5         //单次答题5个
#endif // COMMON_H

2.db.h(数据库类)

#ifndef DB_H
#define DB_H

#include "mysql/mysql.h"
#include 
#include "spdlog/spdlog.h"
#include 


class DB
{
public:   //主机           用户名                    密码              数据库名称
    DB(const char *host, const char *userName,const char *passwd,const char *dbName);
    //执行数据库语句
    bool db_exec(const char *sql);

    //数据库查询
    //[int] sql 数据库查询语句
    //[out] outJson  查询结果保存到Json变量中
    bool db_select(const char *sql,Json::Value &outJson);


private:
    std::mutex _mutex;   //数据库句柄互斥锁
    MYSQL *_mysql;       //数据库的句柄
};

#endif // DB_H

3.myserver(处理客户端事件)

#ifndef MYSERVER_H
#define MYSERVER_H
#include "tcpserver.h"
#include 
#include "db.h"
#include 
#include 
#include "../common.h"

#include 
#include 
#include "user.h"
#include
#define DEBUG


class myserver:public Tcpserver
{
public:
    myserver();

    virtual void connectEvent(TcpSocket *);

    virtual void readEvent(TcpSocket *);

    virtual void writeEvent(TcpSocket *);

    virtual void closeEvent(TcpSocket *,short);
private:
        //发送数据
        void writeData(TcpSocket *s,const Json::Value &inJson);

        //用户注册
        void Register(TcpSocket *s,const Json::Value &inJson);

        //用户登陆
        void Login(TcpSocket *s,const Json::Value &inJson);

        //获取个人训练赛题目
        void singleGetQuestion(TcpSocket *s);

        //初始化rank积分对照表
        void initRankMap();

        //进行排位
        void Rank(TcpSocket *s);

       //开始对决
        void startRank(TcpSocket *first,TcpSocket *second);

         //rank  结果
        void rankResult(TcpSocket *s,const Json::Value &inJson);

        //rank 回答一道问题
        void rankAnswerOneQuestion(TcpSocket *s,const Json::Value &inJson);

private:
    std::shared_ptr _log; //记录日志的句柄
    DB * _db; //数据库句柄

    std::mutex _userlock;
    std::map _users;    //在线用户链表  键为用户名  值为用户指针
    //key  rank积分
    //值   对应的段位说明
    std::map _rankMap;    //rank积分对照表

    //key : rank积分
    //值  : 参与rank的用户socket句柄
    std::mutex _rankLock;
    std::map  _rankQueue;  //待排位匹配队列
};

#endif // MYSERVER_H

4.Tcpserver(监听)

#ifndef TCPSERVER_H
#define TCPSERVER_H
#include "thread.h"
#include 
#include 
#include 
#include 

#include 
#include 
#include "tcpsocket.h"
class TcpSocket;
class Tcpserver
{
    friend class TcpSocket;
    public:
        Tcpserver(int threadNum = 8);//默认线程为8个

        int listen(int port,const char * ip = NULL); //监听ip
        //让服务器开始运行
        void start();



    protected:
        //用户监听回调函数,有客户端连接时调用该函数
        static void listenCb(struct evconnlistener *,evutil_socket_t fd,struct sockaddr*clientAdd,int ,void *data);
        //监听处理函数
        void listenEvent(evutil_socket_t fd,struct sockaddr_in*clientAddr);

        //*************************虚函数取具体处理客户端的逻辑*************************
        //客户端链接事件
        virtual void connectEvent(TcpSocket *){}
        //客户端可读事件
        virtual void readEvent(TcpSocket *){}
        //可写事件
        virtual void writeEvent(TcpSocket *){}
        //关闭事件
        virtual void closeEvent(TcpSocket *,short){}

    private:
        int m_threadNum;     //线程个数
        Thread *m_threadPool;//线程池
        struct event_base *m_base;
        struct evconnlistener *m_listener;//监听客户端的链接

        int m_nextThread;//记录下一个线程的下表  用于轮循
};

#endif // TCPSERVER_H

5.Tcpsocket(与客户端通信)

#ifndef TCPSOCKET_H
#define TCPSOCKET_H
//通信类  负责与客户端进行通信
#include "tcpserver.h"
#include 
class Tcpserver;

class TcpSocket
{
public:
        TcpSocket(Tcpserver *tcpServer,struct bufferevent *bev,char *ip,u_int16_t port);
        //可读事件回调函数
        static void readEventCb(struct bufferevent *bev,void *ctx);
        //可写事件回调函数
        static void writeEventCb(struct bufferevent *bev,void *ctx);
        //异常事件回调函数
        static void closeEventCb(struct bufferevent *bev,short what,void *ctx);


        char *getIp();         //获取IP地址

        u_int16_t getPort();   // 获取端口

        //从客户端读数据
        int readData(void *data,int size);
        //往客户端写数据
        int writeData(const void *data,int size);

        void setUserName(std::string name);


        std::string getUserName();


    private:
        static Tcpserver *m_tcpServer;     //服务器类对象
        struct bufferevent *m_bev;  //与客户端通信的句柄
        char *m_ip;                 //客户端的IP地址
        u_int16_t m_port;           //客户端使用的端口

        std::string _userName;              //当前用户名
};

#endif // TCPSOCKET_H

6.Thread.h(线程池)

#ifndef THREAD_H
#define THREAD_H
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
class Thread
{
public:
    Thread();
   void start();//线程运行
    //获取事件集合base
    struct event_base*getBase();
protected:
    static void *worker(void*);//线程的工作函数

    static void pipeRead(evutil_socket_t,short,void*);//回调函数必须静态函数
    void run(); //线程的逻辑处理函数

private:
    struct event_base *m_base;// 事件集合
    pthread_t m_threadId;   //线程 I D

    int m_pipeReadFd;     //管道的读段
    int m_pipeWriteFd;   //管道的写段
    struct event m_pipeEvent; //管道事件
};

#endif // THREAD_H

7.User.h(用户类)

#ifndef USER_H
#define USER_H
#include "tcpsocket.h"
#include 

class User
{
public:
    User(std::string n,std::string p,int  rank,TcpSocket *s);

    TcpSocket *getSocket();

   const char *getName();

   int getRank();

   void setRank(int rank);
private:
    std::string _userName;      //用户名
    std::string _passwd;        //用户密码
    int _rank;                   //rank分数


    TcpSocket *_s;              //通信套接字类
};

#endif // USER_H

main.cpp

#include 
#include "thread.h"
#include "tcpserver.h"
#include "myserver.h"
#include 
using namespace std;


int main()
{
    myserver s;
    s.listen(8787);
    s.start();
    return 0;
}

db.cpp

#include "db.h"

DB::DB(const char *host, const char *userName,const char *passwd,const char *dbName)
{
    printf("正在构造DB\n");
   //初始化数据库句柄
    _mysql = mysql_init(NULL);
    if(_mysql == NULL)
    {
        spdlog::get("BrainStorm")->error("mysql_init error\n");

        exit(-1);
    }
    //链接mysql服务器
    MYSQL *con = mysql_real_connect(_mysql,host,userName,passwd,dbName,0,NULL,0);
    if(con == NULL)
    {
        spdlog::get("BrainStorm")->error("链接数据库失败:{}\n",mysql_error(_mysql));
        exit(-1);
    }
    if(con == _mysql)
    {
        printf("链接数据库成功\n");
    }
    _mysql = con;
    //设置字符集
    int ret = mysql_query(_mysql,"set names utf8");
    if(ret != 0)
    {
        spdlog::get("BrainStorm")->error("设置字符集失败:%s",mysql_error(_mysql));
        exit(-1);
    }
}
bool DB::db_exec(const char *sql)
{
    std::unique_lock loc(_mutex);//数据库句柄上锁
    int ret = mysql_query(_mysql,sql);
    if(ret != 0)
    {
        spdlog::get("BrainStorm")->error("mysql_query error :%s",mysql_error(_mysql));
        return false;
    }
    return true;
}
bool DB::db_select(const char *sql,Json::Value &outJson)
{
    std::unique_lock loc(_mutex); //数据库句柄上锁
    int ret = mysql_query(_mysql,sql);
    if(ret != 0)
    {
        spdlog::get("BrainStorm")->error("mysql_query error :%s",mysql_error(_mysql));
        return false;
    }
    //从myaql服务器下载查询结果
    MYSQL_RES *sql_res =  mysql_store_result(_mysql);
    if(sql_res == NULL)
    {
        if(mysql_errno(_mysql) == 0)
        {
            return true;
        }
        else
        {
              spdlog::get("BrainStorm")->error("mysql_query error :%s",mysql_error(_mysql));
        }
    }
    MYSQL_ROW row; //从结果集中一行一行的取出数据
    unsigned int num_fields =  mysql_num_fields(sql_res); //获取列数
    MYSQL_FIELD *fetch_field = mysql_fetch_field(sql_res);   //获取表头
    //一行一行的获取数据

    while(row = mysql_fetch_row(sql_res))
        {
                // 获取一行数据
            for(unsigned int i = 0;i < num_fields;i++)
            {
                outJson[fetch_field[i].name].append(row[i]);
            }
        }
    mysql_free_result(sql_res);
    return true;
}

myserver.cpp

#include "myserver.h"

using namespace  spdlog;
myserver::myserver()
{
   initRankMap();
#ifdef DEBUG
    _log = spdlog::stdout_color_mt("BrainStorm");

#else

   _log = spdlog::rotating_logger_mt("BrainStorm","BrainStorm",1024*1024*5,3);
    _log->flush_on(spdlog::level::info);
#endif
    _db = new DB(NULL,"root","123456","BrainStorm");

}

void myserver::connectEvent(TcpSocket *s)
{
    _log->info("有一个新连接[{}:{}]",s->getIp(),s->getPort());
}

void myserver::readEvent(TcpSocket *s)
{
    char buf[1024] = {0};
    while (1)
    {
        int len = 0;
        s->readData(&len,sizeof(len));
        if( len<= 0)
        {
            break;
        }
        s->readData(buf,len);

        //发过来的是json数据  进行数据解析
        Json::Value root;
        Json::Reader reader;//json解析器
        if(!reader.parse(buf,root))
        {
            _log->error("数据解析失败");
            return;
        }

        int cmd = root["cmd"].asInt();
        switch (cmd)
        {
        case REGISTER:    //注册
            Register(s,root);
            break;
        case LOGIN:       //登录
            Login(s,root);
            break;
        case SINGLE_GETQUESTION:    //获取个人训练赛题目
            singleGetQuestion(s);
            break;
        case RANK:    //进行排位
            Rank(s);
            break;
        case ANSWER:    //答完一题进行消息的转发
            rankAnswerOneQuestion(s,root);
            break;
        case RANKRESULT:    //答题结果
            rankResult(s,root);
            break;
        default:
            break;
        }
    }
}
void myserver::writeEvent(TcpSocket *)
{

}

void myserver::closeEvent(TcpSocket *s,short)
{
    auto it1 = _users.find(s->getUserName());
    if(it1 == _users.end())
    {
         _log->info("[{}:{}] loginout ",s->getIp(),s->getPort());
    }
    else
    {

        char sql[100] = {0};
        printf("测试1\n");
        //将用户从 等待  rank 的队列中删除
        {
                std::unique_lock _lock(_rankLock);
                int rank = _users[s->getUserName()]->getRank();
                auto it = _rankQueue.find(rank);
                if(it != _rankQueue.end())
                {
                    printf("队列踢出测试\n");
                    _rankQueue.erase(it);
                }
        }

        std::unique_lock _lock(_userlock);
        std::map::iterator it = _users.begin();

        while(it != _users.end())
        {

            if(it->second->getSocket() == s)
            {
                sprintf(sql,"update user set rank = '%d' where name = '%s'",it->second->getRank(),it->second->getName());  //更新段位
                _db->db_exec(sql);
                printf("移除在线用户测试\n");
                _users.erase(it);//移除在线用户
                _log->info("用户{}[{}:{}] loginout ",it->second->getName(),s->getIp(),s->getPort());
                //释放user
                delete  it->second;
                return;
            }
                it++;
        }
    }

}
//发送数据
void myserver::writeData(TcpSocket *s,const Json::Value &inJson)
{
    std::string data = inJson.toStyledString();
    s->writeData(data.c_str(),data.length());
}

void myserver::Register(TcpSocket *s,const Json::Value &inJson)
{
    std::string userName = inJson["userName"].asString();
    std::string passwd = inJson["passwd"].asString();

    //检测用户是否存在

    char sql[100] = {0};
    sprintf(sql,"select *from user where name = '%s' and passwd = '%s'",userName.c_str(),passwd.c_str());

    int result = OK;

    Json::Value outJson;

    bool ret = _db->db_select(sql,outJson);

    if(!ret)
    {
        result = ERROR;
       _log->error("Register select user error");
    }

    if(outJson.isMember("name"))
    {

        result = USEREXIST;
    }
    else
    {
        sprintf(sql,"insert into user(name,passwd,rank) values('%s','%s',0)",userName.c_str(),passwd.c_str());
        bool ret = _db->db_exec(sql);
        if(!ret)
        {
            result = ERROR;
            _log->error("Register insert user error");
        }
        else
         {
            _log->info("Register user = {} succeed",userName);
         }
    }

    Json::Value json;
    json["cmd"] = REGISTER;
    json["result"] = result;

    writeData(s,json);

}


void myserver::Login(TcpSocket *s,const Json::Value &inJson)
{
    std::string userName = inJson["userName"].asString();
    std::string passwd = inJson["passwd"].asString();
    int rank = 0;
    //检测用户是否已经注册

    char sql[100] = {0};
    sprintf(sql,"select *from user where name = '%s' and passwd = '%s'",userName.c_str(),passwd.c_str());

    int result = OK;

    Json::Value outJson;

    bool ret = _db->db_select(sql,outJson);

    if(!ret)
    {
        result = ERROR;
       _log->error("login select user error");
    }

    if(outJson.isMember("name"))   //用户存在表明已经注册过了
    {
        std::unique_lock lock(_userlock);
        if(_users.find(userName) != _users.end())  //说明用户已经登录
        {
            result = USERLOGIN;
        }
        else
        {
            int i = 0;
             rank = atoi(outJson["rank"][i].asString().c_str());//字符串转整形
            User *user = new User(userName,passwd,rank,s);
            _users.insert(make_pair(userName,user));//插入容器
            _log->info("用户{}[{}:{}] login ",userName,s->getIp(),s->getPort());
            s->setUserName(userName);
        }
    }
    else
    {
        result = NAMEORPASSWD;
    }

    Json::Value json;
    json["cmd"] = LOGIN;
    json["result"] = result;
    json["userName"] = userName;
    json["rank"]    = _rankMap[rank];

    writeData(s,json);
}

void myserver::singleGetQuestion(TcpSocket *s)
{
    char sql[100] = {0};
    sprintf(sql,"select *from question order by rand() limit %d",QUESTION_NUM);

    int result = OK;
    Json::Value outJson;
    bool ret = _db->db_select(sql,outJson);

    if(!ret || outJson["question"].size() != QUESTION_NUM)
    {
        result = ERROR;
       _log->error("login select question error");
    }
    else
    {
        Json::Value json;
        json["cmd"] = SINGLE_GETQUESTION;
        json["result"] = result;
        json["question"] = outJson;

        _log->info("用户{}[{}:{}]获取题目:{}\n",s->getUserName(),s->getIp(),s->getPort(),json.toStyledString());

        writeData(s,json);
    }
}

void myserver::startRank(TcpSocket *first,TcpSocket *second)
{
        char sql[100] = {0};
        sprintf(sql,"select * from question order by rand() limit %d",QUESTION_NUM);

        int result = OK;
        Json::Value outJson;
        bool ret = _db->db_select(sql, outJson);
        if(!ret || outJson["question"].size() != QUESTION_NUM)
        {
            result = ERROR;
            _log->error("startRank select question error");

        }

        Json::Value json;
        json["cmd"] = RANK;
        json["result"] = result;
        json["question"] = outJson;
//first user
        json["enemyName"] = second->getUserName();  //对手的名字
        json["enemyRank"] = _rankMap[_users[second->getUserName()]->getRank()]; //对手的分数--段位
        json["enemyScore"] = 0;
        writeData(first, json);  //first是自己  second是对手


//second user
        json["enemyName"] = first->getUserName();  //对手的名字
        json["enemyRank"] = _rankMap[_users[first->getUserName()]->getRank()]; //对手的分数--段位
        json["enemyScore"] = 0;

        writeData(second, json);

        _log->info("获取 rank 题目 :  {}\n",json.toStyledString());

}


void myserver::Rank(TcpSocket *s)
{
    TcpSocket *other = NULL; //对手
    int rank = _users[s->getUserName()]->getRank();    //当前用户 rank 积分
    std::unique_lock lock(_rankLock);
    //查找同一段位的对手
    std::map::iterator it = _rankQueue.find(rank);
    if(it != _rankQueue.end())
    {
        other = it->second;
        _rankQueue.erase(it);
    }
    else
    {
        //查找其他段位的选手,积分值相差的绝对值小于5的都可以进行对决
        for(int i = 1;i <= 5 ;i++)
        {
            it = _rankQueue.find(rank+i);
            if(it != _rankQueue.end())
            {
                other = it->second;
                _rankQueue.erase(it);
                break;
            }
            it = _rankQueue.find(rank-i);
            if(it != _rankQueue.end())
            {
                other = it->second;
                _rankQueue.erase(it);
                break;
            }
        }
    }
     _log->info("  rank 分数 :  {}\n",rank);
    if(other == NULL)//如果没有找到匹配的用户  将他加入等候队列
    {
        _rankQueue.insert(std::make_pair(rank, s));
        _log->info("当前等侯  rank  人数 :  {}\n",_rankQueue.size());
    }
    else //如果找到 开始对决 进行发题
    {
        startRank(s,other);
    }

}

void myserver::rankAnswerOneQuestion(TcpSocket *,const Json::Value &inJson)
{
    std::string enemyName = inJson["enemyName"].asString();

    User *user = _users[enemyName];

    Json::Value json;
    json["cmd"]        = ANSWER;
    json["enemyscore"] = inJson["score"].asInt();
    json["enemyQuestionId"] = inJson["questionId"].asInt();

    writeData(user->getSocket(),json);
}

void myserver::initRankMap()
{
    char buf[100] = {0};
    int rank = 0;
    int num = 0;
    for(int i = 0; i < 100;i++)
    {
        if(i < 9)
        {
            rank = i / 3;
            num  = i % 3;
            sprintf(buf,"青铜%d %d颗星",3-rank,num +1);
        }
        else if(9 <= i && i < 18)
        {
            rank = (i-9) / 3;
            num  = (i-9) % 3;
            sprintf(buf,"白银%d %d颗星",3-rank,num+1);
        }
        else if(18 <= i && i < 34)
        {
            rank = (i-18) / 4;
            num  = (i-18) % 4;
            sprintf(buf,"黄金%d %d颗星",4-rank,num+1);
        }
        else if(34 <= i && i < 50)
        {
            rank = (i-34) / 4;
            num  = (i-34) % 4;
            sprintf(buf,"铂金%d %d颗星",4-rank,num+1);
        }
        else if(50 <= i && i < 75)
        {
            rank = (i-50) / 5;
            num  = (i-50) % 5;
            sprintf(buf,"钻石%d %d颗星",5-rank,num+1);
        }
        else if(75 <= i && i < 100)
        {
            rank = (i-75) / 5;
            num  = (i-75) % 5;
            sprintf(buf,"星耀%d %d颗星",5-rank,num+1);
        }
        _rankMap.insert(std::make_pair(i,buf));
    }
    /*
        for(int i = 0; i < 100; i++)
        {
            std::cout< lcok(_userlock);
    User *user = _users[s->getUserName()];
    printf("用户段位%s:%d\n",user->getName(),user->getRank());
    int score = inJson["score"].asInt();
    int enemyscore = inJson["enemyscore"].asInt();

    if(score < enemyscore)
    {
        user->setRank(user->getRank()-1);
    }
    else if(score > enemyscore)
    {
        user->setRank(user->getRank()+1);
    }
    printf("用户段位%s:%d\n",user->getName(),user->getRank());
    Json::Value json;
    json["cmd"]        = RANKRESULT;
    json["newRank"] = _rankMap[user->getRank()];
    writeData(s,json);
}

Tcpserver.cpp

#include "tcpserver.h"

Tcpserver::Tcpserver(int threadNUm):m_nextThread(0)
{
    if(threadNUm <= 0)
    {
        printf("threadNUM <=0\n");
        exit(-1);
    }
    //创建线程池--线程数组
    m_threadNum = threadNUm;
    m_threadPool = new Thread[threadNUm];
    if(m_threadPool == NULL)
    {
        printf("create threadpool error\n");
        exit(-1);
    }
    m_base =event_base_new();
    if(!m_base)
    {
        printf("could not initialize libevent\n");
        exit(-1);
    }
}


//有客户端连接时调用该函数                                     fd是与客户端通信的描述符
void Tcpserver::listenCb(struct evconnlistener *,evutil_socket_t fd,struct sockaddr*clientAdd,int ,void *data)
{
    //printf("有客户端请求链接\n");
    Tcpserver *p = (Tcpserver *)data;
    p->listenEvent(fd,(struct sockaddr_in *)clientAdd);
}
//监听处理函数
void Tcpserver::listenEvent(evutil_socket_t fd,struct sockaddr_in*clientAddr)
{
    char *ip = inet_ntoa(clientAddr->sin_addr);//客户端的ip地址
    uint16_t port = ntohs(clientAddr->sin_port);//客户端使用的端口
    //从线程池中取选择一个线程取处理客户端的请求
    //以轮循的方式取选择线程
    struct event_base *base = m_threadPool[m_nextThread].getBase();
    m_nextThread = (m_nextThread+1) % m_threadNum;
    struct bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);  //该bufferevent监听fd 下面调用相应的函数
    if(!bev)
    {
        printf("Error constructing bufferevent!");
        event_base_loopbreak(base);
        return;
    }

    //创建一个通信对象
    TcpSocket *s = new TcpSocket(this,bev,ip,port);
    //单独封装一个类负责和客户端的通信

   bufferevent_setcb(bev,s->readEventCb,s->writeEventCb,s->closeEventCb,s);//设置回调函数函数  对应客户端发来什么请求调用相应函数
   bufferevent_enable(bev,EV_WRITE);//打开读写开关  使能
   bufferevent_enable(bev,EV_READ);
   bufferevent_enable(bev,EV_SIGNAL);

    //调用客户端链接事件
   connectEvent(s);
}

int Tcpserver::listen(int port,const char *ip)
{
    struct sockaddr_in sin;
    memset(&sin,0,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    if(ip != NULL)
    {
        inet_aton(ip,&sin.sin_addr);
    }
    //监听客户端的链接                     有客户端链接的时调用listenCb
    m_listener = evconnlistener_new_bind(m_base,listenCb,this,LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE,-1,(struct sockaddr*)&sin,sizeof(sin));

    if(!m_listener)
    {
        printf("Could not create a listener!\n");
        return -1;
    }
   //开启线程池
    for(int i = 0;i < m_threadNum;i++)
    {
        m_threadPool[i].start();//开启线程     内部包含创建线程
        printf("线程 %d 启动\n",i+1);
    }

    return 0;//成功返回0  失败返回-1
}
void Tcpserver::start()
{
    event_base_dispatch(m_base);

    evconnlistener_free(m_listener);
    event_base_free(m_base);
    printf("done\n");
}

Tcpsocket.cpp

#include "tcpsocket.h"

Tcpserver *TcpSocket::m_tcpServer =NULL;
TcpSocket::TcpSocket(Tcpserver *tcpServer,struct bufferevent *bev,char *ip,u_int16_t port)
{
    m_tcpServer = tcpServer;
    m_bev = bev;
    m_ip = ip;
    m_port = port;
}
//可读事件回调函数  当buffrevent 发来读或者写信号  调用下面的回调函数 回调函数又调用相应的函数进行处理
void TcpSocket::readEventCb(struct bufferevent *,void *ctx)
{
    TcpSocket *s = (TcpSocket *)ctx;
   m_tcpServer->readEvent(s); //调用readevent对发来的json数据包进行解析读取
}
//可写事件回调函数
void TcpSocket::writeEventCb(struct bufferevent *,void *ctx)
{
    TcpSocket *s = (TcpSocket *)ctx;
    m_tcpServer->writeEvent(s);
}
//异常事件回调函数
void TcpSocket::closeEventCb(struct bufferevent *,short what,void *ctx)
{
    TcpSocket *s = (TcpSocket *)ctx;
    m_tcpServer->closeEvent(s,what);
    delete  s;
}
char *TcpSocket::getIp()
{
    return m_ip;
}

u_int16_t TcpSocket::getPort()
{
    return m_port;
}


int TcpSocket::readData(void *data,int size)
{
    return bufferevent_read(m_bev,data,size);
}

int TcpSocket::writeData(const void *data,int size)
{
    return bufferevent_write(m_bev,data,size);
}
void TcpSocket::setUserName(std::string name)
{
    _userName = name;
}
std::string TcpSocket::getUserName()
{
    return _userName;
}

Thread.cpp

#include "thread.h"

Thread::Thread()
{
    m_base = event_base_new();
       if(!m_base)
       {
           printf("Couldn't creat an event_base:exiting\n");
           exit(-1);
       }

       //创建管道
       int fd[2];
       if(pipe(fd) == -1)
       {
           perror("pipe");
           exit(-1);
       }
       m_pipeReadFd = fd[0];
       m_pipeWriteFd = fd[1];
       //让管道事件监听管道的读段
      //如果监听到管道的读段有数据可读          可读事件  永久有效    回调函数
       event_set(&m_pipeEvent,m_pipeReadFd,EV_READ|EV_PERSIST,pipeRead,this);
       //将事件添加到m_base集合中
       event_base_set(m_base,&m_pipeEvent);
       //开始事件的监听
       event_add(&m_pipeEvent,0);






}

void Thread::pipeRead(evutil_socket_t, short, void *)
{

}
void Thread::start()
{
   pthread_create(&m_threadId,NULL,worker,this);

   pthread_detach(m_threadId);  //线程分离
}

void *Thread::worker(void *arg)
{
    Thread *p = (Thread*)arg;
    p->run();  //静态成员函数 无法访问类成员  转到类的成员函数
    return NULL;
}

void Thread::run()
{
    //printf("线程运行开始测试\n");
    //监听base事件集合
    event_base_dispatch(m_base);//循环监听 处理事件
    event_base_free(m_base);

    //printf("线程运行结束测试\n");
    return;
}
struct event_base*Thread::getBase()
{
    return m_base;
}

User.cpp

#include "user.h"

User::User(std::string n,std::string p,int  rank,TcpSocket *s)
    :_userName(n)
    ,_passwd(p)
    ,_rank(rank)
    ,_s(s)
{

}
TcpSocket* User::getSocket()
{
    return _s;
}
const char *User::getName()
{
    return _userName.c_str();
}
int User::getRank()
{
    return _rank;
}
void User::setRank(int rank)
{
    if(rank <= 0)
        rank = 0;
    _rank = rank;
}

五 客户端代码展示

brainstorm.h(具体功能)

#ifndef BRAINSTORM_H
#define BRAINSTORM_H

#include 
#include "communicate.h"
#include 
#include 
#include 
#include 
#include 
#include "../common.h"
namespace Ui {
class BrainStorm;
}


class BrainStorm : public QDialog
{
    Q_OBJECT

public:
    explicit BrainStorm(Communicate *_com,QJsonObject &json,QWidget *parent = 0);
    ~BrainStorm();

private:
    //单人训练获取题目
    void singleGetQuestion();

    //单人训练设置问题
    void singleSetQuestion();

    //单人训练回答问题
    void singleAnswerQuestion(int select);

    //设置对手的得分
    void setEnemyScore();
    //设置自己的得分
    void setSelfScore();

    //设置rank题目
    void rankSetQuestion();

    //排位回答问题
    void rankAnswerQuestion(int select);

    //设置rank结果
    void rankSetResult(QJsonObject &json);

private slots:
    void on_singleButton_clicked();

    void on_single_back_clicked();

    void on_single_start_clicked();

    //单人训练从服务器接收到题目
    void receiveSingleQuestion(QJsonObject json);


    void singleTimerOut();


    void on_pushButton_clicked();

    void on_singleSelectButton1_clicked();

    void on_singleSelectButton2_clicked();

    void on_singleSelectButton3_clicked();

    void on_singleSelectButton4_clicked();

    void on_rankButton_clicked();
    //接受排位
    void Rank(QJsonObject json);


    void rankTimerOut();

    void on_rankSelectButton1_clicked();

    void on_rankSelectButton2_clicked();

    void on_rankSelectButton3_clicked();

    void on_rankSelectButton4_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::BrainStorm *ui;

    Communicate * _com;//通信类指针负责和服务器通信

    QJsonObject _singleQuestion; //单人训练问题

    int _currentSingleQuestion; //当前回答哪一个问题的下标

    QTimer _singleTimer;       //个人训练定时器

    int _singleSec;        //个人训练答题时间

    int _singleScore;      //个人训练得分
    
    //-------------------------------------rank---------------
    QJsonObject _rankQuestion; //rank的题目
    QString _enemyName;      //对手的名字
    QString _enemyRank;      //对手的段位
    int _enemyScore;         //对手的得分

    int _rankSec;         //rank答题计时

    int _myScore;            //自己的得分
    QString _userName;      //自己的名字
    QString _userRank;      //自己的段位

    int _currentRankQuestion; //当前回答哪一个问题的下标
    int _enemyRankQuestion;   //对手当前回答问题的下标


    QTimer _rankTimer;         //rank的定时器
};


#endif // BRAINSTORM_H

communicate.h(通讯)

#ifndef COMMUNICATE_H
#define COMMUNICATE_H

#include 
#include 
#include 
#include 
#include 
#include "../common.h"

class Communicate : public QObject
{
    Q_OBJECT
public:
    explicit Communicate(QObject *parent = nullptr);

    void writeData(const QJsonObject &json);

signals:
    void rstResult(int);   //接受注册信号

    void login(QJsonObject json);   //接登录的信号

    void receiveSingleQuestion(QJsonObject json);   //接受个人训练题目
    
    void Rank(QJsonObject json);   //发送排位信号

public slots:
    void readData();

private:
    QTcpSocket s;
};


#endif // COMMUNICATE_H

login.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include "communicate.h"
#include "../common.h"
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_LoginButton_clicked();

    void on_EnrollButton_clicked();

    void login(QJsonObject json);


private:
    Ui::Widget *ui;

    Communicate * _com;//通信类指针负责和服务器通信
};

#endif // WIDGET_H

register.h

#ifndef REGISTER_H
#define REGISTER_H

#include 
#include 
#include "communicate.h"
#include "../common.h"

namespace Ui {
class Register;
}

class Register : public QDialog
{
    Q_OBJECT

public:
    explicit Register(Communicate *com, QWidget *parent = 0);
    ~Register();

private slots:
    void on_RegisterButton_clicked();

    void on_pushButton_2_clicked();

    void rstResult(int );

private:
    Ui::Register *ui;
    Communicate *_com;
};

#endif // REGISTER_H

brainstorm.cpp

#include "brainstorm.h"
#include "ui_brainstorm.h"
#include

BrainStorm::BrainStorm(Communicate *com, QJsonObject &json, QWidget *parent):
    QDialog(parent),
    ui(new Ui::BrainStorm)
{
    ui->setupUi(this);
    _com = com;

    //ui->mainMenu->show();
    _userName = json["userName"].toString();
    _userRank = json["rank"].toString();

    connect(&_singleTimer,SIGNAL(timeout()),this,SLOT(singleTimerOut()));
    connect(_com, SIGNAL(receiveSingleQuestion(QJsonObject)), this, SLOT(receiveSingleQuestion(QJsonObject)));

    connect(_com, SIGNAL(Rank(QJsonObject)), this, SLOT(Rank(QJsonObject)));

    connect(&_rankTimer,SIGNAL(timeout()),this,SLOT(rankTimerOut()));



    this->setWindowIcon(QIcon("D:\\Qmake\\Picture\\pk.jpg"));
    this->setWindowTitle("答题");

    QMovie *movie = new QMovie ("D:\\Qmake\\Picture\\111.gif" );
    ui->background->setMovie(movie);
    movie->start() ;
    ui->background->setScaledContents(true);

    ui->rankButton->setStyleSheet("background-color: rgb(0, 170, 255);");
    ui->singleButton->setStyleSheet("background-color: rgb(0, 170, 255);");


    QMovie *movie4 = new QMovie ("D:\\Qmake\\Picture\\R-C (2).gif" );
    ui->label_4->setMovie(movie4);
    movie4->start() ;
    ui->label_4->setScaledContents(true);
    ui->rank_wait->setStyleSheet("background-color: rgb(252, 252, 252);");

    ui->label_5->setPixmap(QPixmap("D:\\Qmake\\Picture\\R-C.jpg"));//QIcon
    ui->label_5->setScaledContents(true);





}



BrainStorm::~BrainStorm()
{
    delete ui;
}

//个人训练 计时器
void BrainStorm::singleTimerOut()
{
    --_singleSec;
    if(_singleSec == 0)
    {
        ui->singleResult->setText("回答错误");
        QString str = QString("本次得分,%1").arg(_singleScore);
        ui->singleScore->setText(str);
        _singleTimer.stop();
        ui->stackedWidget->setCurrentWidget(ui->single_score);
    }
    ui->lcdNumber->display(_singleSec);
}



//个人训练从服务器获取题目
void BrainStorm::singleGetQuestion()
{
    QJsonObject json;
    json["cmd"] = SINGLE_GETQUESTION;

    _com->writeData(json);
}


//进入个人训练模式
void BrainStorm::on_singleButton_clicked()
{
    ui->stackedWidget->setCurrentWidget(ui->single_menu);
}
//返回上一个界面
void BrainStorm::on_single_back_clicked()
{
    ui->stackedWidget->setCurrentWidget(ui->mainMenu);
}

//开始个人答题
void BrainStorm::on_single_start_clicked()
{
    singleGetQuestion();
}
//设置个人训练问题
void BrainStorm::singleSetQuestion()
{   //问题
    ui->singlequestion->setText(_singleQuestion["question"].toArray().at(_currentSingleQuestion).toString());
    //选项
    ui->singleSelectButton1->setText(_singleQuestion["selection1"].toArray().at(_currentSingleQuestion).toString());
    ui->singleSelectButton2->setText(_singleQuestion["selection2"].toArray().at(_currentSingleQuestion).toString());
    ui->singleSelectButton3->setText(_singleQuestion["selection3"].toArray().at(_currentSingleQuestion).toString());
    ui->singleSelectButton4->setText(_singleQuestion["selection4"].toArray().at(_currentSingleQuestion).toString());
}
//接受 题目
void BrainStorm::receiveSingleQuestion(QJsonObject json)
{

    _singleQuestion = json;
    _singleSec = 10;
    _currentSingleQuestion = 0;//当前题号为0
    _singleScore = 0;
    ui->lcdNumber->display(_singleSec);
    singleSetQuestion();

    //开启定时器
    _singleTimer.start(1000);
    ui->stackedWidget->setCurrentWidget(ui->single_runing);
}

//答题结束 得分界面返回
void BrainStorm::on_pushButton_clicked()
{
    ui->stackedWidget->setCurrentWidget(ui->mainMenu);
}

//个人训练答题
void BrainStorm::singleAnswerQuestion(int select)
{  //回答正确
    if(select == _singleQuestion["answer"].toArray().at(_currentSingleQuestion).toString().toInt())
    {
        _singleScore += 20;  //根据剩余时间来打分 每题满分20
        _currentSingleQuestion++;    //题目下标++
        singleSetQuestion();  //设置下一题
        _singleSec = 10;
        _singleTimer.stop();
        ui->lcdNumber->display(_singleSec);
        _singleTimer.start(1000);
    }
    else//回答错误
    {
        ui->singleResult->setText("回答错误");
        QString str = QString("本次得分,%1").arg(_singleScore);
        ui->singleScore->setText(str);
        ui->stackedWidget->setCurrentWidget(ui->single_score);
        _singleTimer.stop();
    }
    //题目答完
    if(_currentSingleQuestion == QUESTION_NUM)
    {
        ui->singleResult->setText("恭喜全部回答正确");
        QString str = QString("本次得分,%1").arg(_singleScore);
        ui->singleScore->setText(str);
        ui->stackedWidget->setCurrentWidget(ui->single_score);
        _singleTimer.stop();
    }
}
void BrainStorm::on_singleSelectButton1_clicked()
{
    singleAnswerQuestion(1);
}

void BrainStorm::on_singleSelectButton2_clicked()
{
    singleAnswerQuestion(2);
}

void BrainStorm::on_singleSelectButton3_clicked()
{
    singleAnswerQuestion(3);
}

void BrainStorm::on_singleSelectButton4_clicked()
{
    singleAnswerQuestion(4);
}



//rank部分---------------------------------------------------------------------------

void BrainStorm::on_rankButton_clicked()
{
    QJsonObject json;
    json["cmd"] = RANK;

    _com->writeData(json);
    //跳转到等待界面
    ui->stackedWidget->setCurrentWidget(ui->rank_wait);
}

void BrainStorm::rankTimerOut()
{
    _rankSec--;
    if(_rankSec == 0)
    {
        if(ui->rankSelectButton1->isEnabled()) //判断是否答题
        {
             _currentRankQuestion++;
        }
        rankSetQuestion();
        _rankSec = 10;
    }
    ui->lcdNumber_2->display(_rankSec);
}

//设置对手的得分
void BrainStorm::setEnemyScore()
{
    QString str = QString("%1(%2): %3").arg(_enemyName,-5).arg(_enemyRank).arg(_enemyScore);
    ui->enemyStatus->setText(str);
}
void BrainStorm::setSelfScore()
{
    QString str = QString("%1(%2): %3").arg(_userName,-5).arg(_userRank).arg(_myScore);
    ui->selfStatus->setText(str);
}
void BrainStorm::rankSetQuestion()
{
   //问题
   ui->rankQuestion->setText(_rankQuestion["question"].toArray().at(_currentRankQuestion).toString());
   //选项
   ui->rankSelectButton1->setText(_rankQuestion["selection1"].toArray().at(_currentRankQuestion).toString());
   ui->rankSelectButton2->setText(_rankQuestion["selection2"].toArray().at(_currentRankQuestion).toString());
   ui->rankSelectButton3->setText(_rankQuestion["selection3"].toArray().at(_currentRankQuestion).toString());
   ui->rankSelectButton4->setText(_rankQuestion["selection4"].toArray().at(_currentRankQuestion).toString());

   ui->rankSelectButton1->setEnabled(true);  //按钮恢复可用状态
   ui->rankSelectButton2->setEnabled(true);
   ui->rankSelectButton3->setEnabled(true);
   ui->rankSelectButton4->setEnabled(true);
   //清空样式
   ui->rankSelectButton1->setStyleSheet("");
   ui->rankSelectButton2->setStyleSheet("");
   ui->rankSelectButton3->setStyleSheet("");
   ui->rankSelectButton4->setStyleSheet("");
   if(_currentRankQuestion == QUESTION_NUM)
   {
       _rankTimer.stop();
       //将结果发送给服务器
       QJsonObject json;
       json["cmd"] = RANKRESULT;
       json["score"] = _myScore;
       json["enemyscore"] = _enemyScore;

       _com->writeData(json);
   }
}

void BrainStorm::rankAnswerQuestion(int select)
{
    //计算得分
    if(select == _rankQuestion["answer"].toArray().at(_currentRankQuestion).toString().toInt())
        _myScore += 20;

    setSelfScore();
    _currentRankQuestion++;

    //判断是否跳到下一题
    if(_currentRankQuestion == _enemyRankQuestion)//自己和对象的问题下标相等则进入下一题
    {
        _rankSec = 10;
        _rankTimer.stop();
        ui->lcdNumber_2->display(_rankSec);
        _rankTimer.start(1000);
        rankSetQuestion();
    }
    QJsonObject json;
    json["cmd"] = ANSWER;
    json["enemyName"]    = _enemyName;
    json["score"]        = _myScore;
    json["questionId"]   = _currentRankQuestion;

    _com->writeData(json);
}

void BrainStorm::rankSetResult(QJsonObject &json)
{
    QString newRank = json["newRank"].toString();
    if(_myScore == _enemyScore)
    {
        ui->rankResult->setText("平局");
    }
    else if(_myScore < _enemyScore)
    {
        ui->rankResult->setText("失败");
    }
    else if(_myScore > _enemyScore)
    {
        ui->rankResult->setText("胜利");
    }

    QString str = QString("%1  --->  %2").arg(_userRank).arg(newRank);
    ui->newRank->setText(str);
    _userRank = newRank;

    ui->stackedWidget->setCurrentWidget(ui->rank_result);
    std::cout<< "Rankresult"<lcdNumber_2->display(_rankSec);

        _currentRankQuestion= 0;
        _enemyRankQuestion = 0;


        setEnemyScore();
        setSelfScore();
        rankSetQuestion();

        _rankTimer.start(1000);
        ui->stackedWidget->setCurrentWidget(ui->rank_running);
    }
    else if(cmd == ANSWER)
    {
        _enemyScore = json["enemyscore"].toInt();
        _enemyRankQuestion  = json["enemyQuestionId"].toInt();
        setEnemyScore();

        if(_currentRankQuestion ==_enemyRankQuestion)
        {
            _rankSec = 10;
            _rankTimer.stop();
            ui->lcdNumber_2->display(_rankSec);
            _rankTimer.start(1000);
            rankSetQuestion();
        }
    }
    else if(cmd == RANKRESULT)
    {
        rankSetResult(json);
    }
}



void BrainStorm::on_rankSelectButton1_clicked()
{
    ui->rankSelectButton1->setStyleSheet("background-color: rgb(255, 170, 255);");
    ui->rankSelectButton1->setEnabled(false);
    ui->rankSelectButton2->setEnabled(false);
    ui->rankSelectButton3->setEnabled(false);
    ui->rankSelectButton4->setEnabled(false);
    rankAnswerQuestion(1);
}

void BrainStorm::on_rankSelectButton2_clicked()
{
    ui->rankSelectButton2->setStyleSheet("background-color: rgb(255, 170, 255);");
    ui->rankSelectButton1->setEnabled(false);
    ui->rankSelectButton2->setEnabled(false);
    ui->rankSelectButton3->setEnabled(false);
    ui->rankSelectButton4->setEnabled(false);
    rankAnswerQuestion(2);
}

void BrainStorm::on_rankSelectButton3_clicked()
{
    ui->rankSelectButton3->setStyleSheet("background-color: rgb(255, 170, 255);");
    ui->rankSelectButton1->setEnabled(false);
    ui->rankSelectButton2->setEnabled(false);
    ui->rankSelectButton3->setEnabled(false);
    ui->rankSelectButton4->setEnabled(false);
    rankAnswerQuestion(3);
}

void BrainStorm::on_rankSelectButton4_clicked()
{
    ui->rankSelectButton4->setStyleSheet("background-color: rgb(255, 170, 255);");
    ui->rankSelectButton1->setEnabled(false);
    ui->rankSelectButton2->setEnabled(false);
    ui->rankSelectButton3->setEnabled(false);
    ui->rankSelectButton4->setEnabled(false);
    rankAnswerQuestion(4);
}

void BrainStorm::on_pushButton_2_clicked()
{
    ui->stackedWidget->setCurrentWidget(ui->mainMenu);
}

communicate.cpp

#include "communicate.h"
#include 
#include 

Communicate::Communicate(QObject *parent) : QObject(parent)
{
    //连接服务器
    s.connectToHost(QHostAddress("192.168.90.82"),8787);
    connect(&s,SIGNAL(readyRead()),this,SLOT(readData()));
}
//如果服务器给客户端发消息
void Communicate::readData()
{
    QByteArray data;  //字节数组
    while(s.bytesAvailable())
    {
        data += s.readAll();
    }
    //数据解析  解析成json字符串
    QJsonDocument dt = QJsonDocument::fromJson(data);
    if(dt.isNull())
    {
        return ;
    }
    QJsonObject root = dt.object();

    //具体的逻辑处理
    int cmd = root["cmd"].toInt();
    qDebug()<<"cmd:"<

login.cpp

#include "login.h"
#include "ui_widget.h"
#include "register.h"
#include 
#include "brainstorm.h"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    _com = new Communicate();
    connect(_com,SIGNAL(login(QJsonObject)),this,SLOT(login(QJsonObject)));


    this->setWindowIcon(QIcon("D:\\Qmake\\Picture\\pk.jpg"));
    this->setWindowTitle("登录");
    this->setStyleSheet("backgrount:gray");

    QPalette pal =this->palette();
    pal.setBrush(QPalette::Background,QBrush(QPixmap("D:\\Qmake\\Picture\\background.png")));
    setPalette(pal);

    ui->EnrollButton->setStyleSheet("background-color: rgb(0, 170, 255);");
    ui->LoginButton->setStyleSheet("background-color: rgb(0, 170, 255);");
 }

Widget::~Widget()
{
    delete ui;
}

void Widget::on_LoginButton_clicked()
{
    QString userName = ui->UsrNameEdit->text();
    QString passWd = ui->PassWordlineEdit->text();

    //登录操作 :将登录信息发送给服务器
    QJsonObject json;
    json["cmd"] = LOGIN;

    json["userName"] = userName;
    json["passwd"]   = passWd;

    _com->writeData(json);

}
void Widget::login(QJsonObject json)
{
    int result  = json["result"].toInt();
    switch (result)
    {
    case OK:
        {
            this->hide();
            BrainStorm *dlg = new BrainStorm(_com,json);

            dlg->show();
            dlg->setAttribute(Qt::WA_DeleteOnClose);
            break;
         }
    case ERROR:
        QMessageBox::information(this,"登录","登录失败,未知错误");
        break;
    case USERLOGIN:
        QMessageBox::information(this,"登录","登录失败,不接重复登录");
        break;
    case NAMEORPASSWD:
        QMessageBox::information(this,"登录","用户名或者密码错误");
        break;
    default:
        break;
     }
}

void Widget::on_EnrollButton_clicked()
{
    this->hide();
    Register reg(_com);
    reg.exec();
    this->show();

}

main.cpp

#include "login.h"
#include 


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();


    return a.exec();
}

register.cpp

#include "register.h"
#include "ui_register.h"
#include 

Register::Register(Communicate *com,QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Register)
{
    ui->setupUi(this);

    this->setWindowTitle("注册");
    _com =com;
    connect(_com,SIGNAL(rstResult(int)),this,SLOT(rstResult(int)));

}

Register::~Register()
{
    delete ui;
}

void Register::on_RegisterButton_clicked()
{
    QString userName = ui->UsrNamelineEdit->text();
    QString passWd = ui->PasswordlineEdit->text();
    //发送注册信息
    QJsonObject json;
    json["cmd"] = REGISTER;
    json["userName"] = userName;
    json["passwd"]   = passWd;
    //给服务器发送数据
    _com->writeData(json);
}
void Register::rstResult(int ret)
{
    switch (ret)
    {
    case OK:
        QMessageBox::information(this,"注册","注册成功");
        break;
    case ERROR:
        QMessageBox::information(this,"注册","注册失败,未知错误");
        break;
    case USEREXIST:
        QMessageBox::information(this,"注册","用户已经存在");
        break;
    default:
        break;
    }
}
void Register::on_pushButton_2_clicked()
{
    close();
}

七 界面展示

基于linux+windows Qt+Mysql 开发的在线答题系统_第1张图片


基于linux+windows Qt+Mysql 开发的在线答题系统_第2张图片

 基于linux+windows Qt+Mysql 开发的在线答题系统_第3张图片

你可能感兴趣的:(linux,数据库,运维,服务器,mysql)