基于Qt的收银点餐系统之解决因网络请求延迟而带来的问题

网络请求在另一个线程中,故主线程中会在进行网络请求的同时继续进行网络请求之后的操作。如果这之后的操作需要用到网络请求的数据,则可能会出现错误。解决方案如下:
1)使主线程暂停
参考:关于在Qt里让程序休眠一段时间的方法总结

QEventLoop loop;
    QObject::connect(&manager2,SIGNAL(finished(QNetworkReply*)),&loop,SLOT(quit()));
    QObject::connect(&manager2,SIGNAL(finished(QNetworkReply*)),this,SLOT(getShopCatalogGoodsList(QNetworkReply*)));
loop.exec();

这样做的原因:QNetworkAccessManager的网络请求API设计本身是异步的,由于我还没太弄懂,我给它直接看成另外开了一个线程,然后把主线程暂停了。需要学习一下slot/signal机制的同步和异步。

2) 利用本地数据库
可以将要用到的数据存在本地数据库中,仅在需要的时候进行网络请求获取数据,其余时候均直接在本地数据库中进行取数。
参考:
数据库简介
安装MySQL数据库
利用QSqlQuery类执行SQL语句

void goodsList::dataPrepare(){

     //店铺中商品分类和对应分类下的商品

    /*判断是否存在catalog 和 shop_catagory_goods_list
    *不存在:建表(动态的建表,goodslist_1.db 原来并不存在),从网络端取数据  用到那些request
    * 存在(更新之后)或者建表之后:得到classifyList和catalogGoodsBeanList[]
    */

    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("goodsList_1.db");
    if(!db.open()) qDebug() << "database failed to open.";
    QSqlQuery query(db);
    int isExistSC = db.tables().contains(QString("shop_classify"));
    int isExistSCGL = db.tables().contains(QString("shop_goods"));
    qDebug() << "table exist?" << isExistSC << " " << isExistSCGL;

    //店铺中商品分类
    if(isExistSC == 0){
        requestForGetClassify();  //初始化classifyList 在getClassify中还有建表操作
    }
    else{
        query.exec("select * from shop_classify");
        //获取查询集的大小
//     qDebug() << "size = " << query.at() + 1;      //qt中不支持用query.size()来获取查询集的大小
        while(query.next()){
            int _id = query.value(0).toInt();
            QString _nm = query.value(1).toString();
            GoodsClassifyBean *bean = new GoodsClassifyBean(_id,_nm);
            qDebug() << "_id _nm in fangwen local DB" << _id <<_nm;
            classifyList.append(bean);
        }
    }

    //不管是上面的哪一种情况,到这之后classifyList应该已经准备好了

    //对应分类下的商品
    if(isExistSCGL == 0) {
        //得到所有的catalogGoodsBeanList,同一建表 
        for(int i = 0 ; i < classifyList.size();i++){
            GoodsClassifyBean* GCItem = classifyList.at(i);
            int catalog3 = GCItem->getId();    //请求分类时的catalog3是分类的id
            tool_catalogGoodsBeanList.clear();
            requestForGetShopCatalogGoodsList(sid,catalog3,0,10);
            qDebug() << "打印 tool_catalogGoodsBeanList.size() = " << tool_catalogGoodsBeanList.size();
            catalogGoodsBeanList[i] = tool_catalogGoodsBeanList;
         }
        **createNewTable("shop_goods");**  
    }
    else{
        for(int i = 0 ; i < classifyList.size();i++){
            int catalog3 = classifyList.at(i)->getId();
            catalogGoodsBeanList[i].clear();
//            query.exec("select * from shop_goods where catalog3 = " + catalog3);  //这样使用变量是不可以的,查不到结果
            query.exec(QString("select * from shop_goods where catalog3 = %1").arg(catalog3));
            while(query.next()){
                int _id = query.value(0).toInt();
                QString _name = query.value(1).toString();
                QString _unit = query.value(2).toString();
                double _price = query.value(3).toDouble();
                int _status = query.value(4).toInt();
                int _catalog3 =  query.value(5).toInt();
                qDebug() << "results in local DB" << _id << _name << _unit << _price;
                GoodsBean *item = new GoodsBean(_id,_name,_unit,_price,_status,_catalog3);
                catalogGoodsBeanList[i].append(item);
            }
        }
    }

    int isExistSC_haha = db.tables().contains(QString("shop_classify"));
    int isExistSCGL_haha = db.tables().contains(QString("shop_goods"));
    qDebug() << "table exist_2?" << isExistSC_haha << " " << isExistSCGL_haha;
}
void goodsList::createNewTable(QString tableName){
    if(tableName == "shop_classify"){
        QSqlQuery query(db);
        query.exec("create table shop_classify(id int primary key , name varchar)");
        for(int i = 0; i < classifyList.size();i++){
           query.prepare("insert into shop_classify(id,name) values(:id,:name)");
           GoodsClassifyBean *item = classifyList.at(i);
           int _id = item->getId();
           QString _nm = item->getName();
         /*
        *之前写成了  query.bindValue(_id, _nm)  所以总是报错  qvector.h : out of memory
        * 在直接查out of memory 无果之后, 自查锁定可能是bindValue用错了
        * 果然用错了,参数意义搞错了。 所以下次遇到新的函数,先看看它的定义
        */
           query.bindValue(0,_id);
           query.bindValue(1,_nm);
           query.exec();
        }

       query.exec("select * from shop_classify");
       while(query.next()){
           qDebug() << "value0 value1" << query.value(0).toInt()<< " " << query.value(1).toString();
//        }
    }
}
采用C/S模式,完成一前台(服务器)对多客服端通讯,用Mysql数据库保存信息; 主要技术: 1.采用TCP/IP协议,容器完成服务端与多客户端的链接 服务端: server=new QTcpServer(this);建立端口 server->listen(QHostAddress::Any,PORT);监听端口 connect(server,SIGNAL(newConnection()),this,SLOT(accpetConnection()));等待用户链接 QTcpSocket* temp = server->nextPendingConnection();建立链接 client.push_back(temp);用户压栈 connect(temp,SIGNAL(readyRead()),this,SLOT(readData()));当端口有数据就读 读数据时先用迭代器遍历容器找到发送信息的客户端,再解析数据并响应 客户端: client=new QTcpSocket(this);建立端口 client->connectToHost(IP,PORT);链接主机 connect(client,SIGNAL(readyRead()),this,SLOT(readData()));端口有数据就读 2.界面布局 服务器 a.主菜单,预订,开台,换台,电子账单功能项采用QToolButton文字置于图片下面,水平布局 b.当前餐台信息与总餐台状态信息用QLabel垂直布局放于主窗体左侧 c.餐台信息采用QGraphicsView+QGraphicsScene+QGraphicsItem布局,view与item需要重写自己的类,Item包括图片与文本信息;将Item放入墙纸scene中,墙纸scene贴到墙view上完成显示。 客户端 a.选择桌号与人数用QLabel,对应的下拉选项用QComboBox,确认,呼叫与结账功能用QToolButton,这些控件水平布局放置于窗体最上方 b.左侧用QTabWidget其中加入特价菜单与我的菜单两个子窗体 c.中间为QGraphicsView+QGraphicsScene+QGraphicsItem布局,布局菜单图片与价格名称,菜单信息服务器发送至客户端与客户端的图片匹配起来。 d.右侧为菜单类型分类按键,采用垂直布局 3.信号与槽机制的运用 a.预订,开台,换台功能的实现:点击对应的按钮触发clicked()信号,与之对应的槽函数中QToolButton *btn = (QToolButton *)sender();区分信号源,弹出对应的子窗体让用户输入相应信息,按确定按钮修改SQL对应Table内容然后发送输入信息信号,主窗体接受到信号调用槽函数(相应窗体成员调用其布局函数重布局)重新布局整个界面(餐台信息与左侧总餐台状态同时更新) b.鼠标悬浮于餐台信息Item时图片放大:改写了QGraphicsSceneMouseEvent事件实现 c.主菜单与电子账单的显示采用QSqlTableModel+QTableView加载整个SQL中相应的Table显示Table内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值