多线程
两种办法:第一种:Qt4.7之前的线程使用的方法(简单);第二种:Qt4.7之后的(灵活–推荐)----connect最后一个参数的作用:默认连接,队列连接,直接连接
现只举例第二种办法:
主线程:为MyWidget中定时器显示
子线程:为MyWork中的业务处理函数
#include <QThread>class MyWidget : public QWidget
{Q_OBJECTpublic:explicit MyWidget(QWidget *parent = 0);~MyWidget();// 开始按钮(主线程)void slotStart();// 关闭按钮(主线程)void slotStop();// 开始按钮(子线程)void slotStart_1();// 关闭按钮(子线程)void slotStop_1();// 定时器void slotTimeout();// 关闭线程void slotCloseThread();signals:void sigWorking();private:Ui::MyWidget *ui;QTimer* mytimer;MyWork *work;QThread* pthread;
};
最主要的部分:1.业务对象(自己写的业务类) 2.子线程类QThread类 3.移动业务对象到子线程moveToThread 4.子线程工作connect
MyWidget::MyWidget(QWidget *parent) : QWidget(parent),ui(new Ui::MyWidget)
{ui->setupUi(this);/* 多线程使用注意事项:* 1. 业务对象, 构造的时候不能指定父对象* 2. 子线程中不能处理ui窗口(ui相关的类)* 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口*/mytimer = new QTimer(this);// 1. 业务对象work = new MyWork();// 2. 子线程类pthread = new QThread(this);// 3. 移动业务对象到子线程work->moveToThread(pthread);// 5. 子线程工作connect(this, &MyWidget::sigWorking, work, &MyWork::doMyWork);connect(ui->start, &QPushButton::clicked, this, &MyWidget::slotStart);connect(ui->stop, &QPushButton::clicked, this, &MyWidget::slotStop);connect(ui->start_1, &QPushButton::clicked, this, &MyWidget::slotStart_1);connect(ui->stop_1, &QPushButton::clicked, this, &MyWidget::slotStop_1);// 定时器connect(mytimer, &QTimer::timeout, this, &MyWidget::slotTimeout);// 窗口析构的时候干掉线程connect(this, &MyWidget::destroyed, this, &MyWidget::slotCloseThread);qDebug() << QThread::currentThread() << "main thread";/* connect 的第 5 参数* 1. 自动连接 -- 默认* 多线程 -- 指定队列连接* 单线程 -- 指定直接连接* 2. 队列连接 -- 多线程* 槽函数在信号接受者(receiver)所在的线程中执行* 3. 直接连接 -- 单线程* 信号和槽函数在同一个线程中执行*/
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::slotStart()
{if(mytimer->isActive() == true){qDebug() << "mytimer->isActive() == true";return;}qDebug() << "mytimer->start";mytimer->start(500);}void MyWidget::slotStop()
{mytimer->stop(); //此按钮主线程(MyWidget计时器)暂停
}void MyWidget::slotStart_1()
{if(pthread->isRunning()){qDebug() << "pthread->isRunning()";return;}qDebug() << "pthread->start";// 4. 启动子线程pthread->start();work->setFlage(false);// 发信号, 让子线程工作emit sigWorking();
}void MyWidget::slotStop_1()
{qDebug() << "slotStop_1";work->setFlage(true);pthread->quit();}
void MyWidget::slotTimeout()
{static int num = 0;ui->lcdNumber->display(num++);
}void MyWidget::slotCloseThread()
{work->setFlage(true);pthread->quit();pthread->wait(); // 等待线程手头上的工作处理完成
}
#include <QThread>class MyWork : public QObject
{Q_OBJECT
public:explicit MyWork(QObject *parent = 0);// 业务处理函数void doMyWork();void setFlage(bool bl);signals:void sigDone();public slots:
private:bool isStop;
};
MyWork::MyWork(QObject *parent) : QObject(parent)
{isStop = false;
}void MyWork::doMyWork()
{qDebug() << "isStop1:"<<isStop;while(!isStop){qDebug() << "isStop2:"<<isStop;if(isStop){break;}// 操作QThread::sleep(1); // 当前线程处理操作用了1s// 每执行一次循环发一次信号emit sigDone();qDebug() << QThread::currentThread() << "sub thread";// QMessageBox::aboutQt(NULL);}
}void MyWork::setFlage(bool bl)
{qDebug() << "setFlage:"<<bl;isStop = bl;
}
最后效果:
数据库操作
1.QSqlDataBase:数据库类,用来添加数据库
pro文件中添加sql
添加头文件:
#include <QSqlDatabase>
#include <QMessageBox>
#include <QSqlError>//添加一个mysql数据库//1.QSQLITE-->XX.db文件 2.QMYSQL//QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); //使用QMYSQL暂时还有一点问题,这里使用QSQLITE,本地的db文件做QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("TestResult.db");//连接的数据库名TestResult.db//打开数据库if(db.open()==false){//弹窗提示QMessageBox::warning(this,"warning",db.lastError().text());}else{QMessageBox::warning(this,"warning","db.open");}
2.QSqlQuery:数据库查询类,(需要会一些SQL语句)
添加一条记录:
//增删查改 ...qDebug()<<"QSqlQuery query";//添加一条记录 QSqlQuery需要用到SQL语句QSqlQuery query;QString sql = "insert into people(name,age) values('zzz',123)"; //需要db文件中有people表,表中有name和age字段query.exec(sql);
批处理方式一:
//2.批处理方式一:预处理 ---通配符:‘?’,odbc风格的通配符query.prepare("insert into people(name,age) values(?,?)"); //要注意格式不能写错了//添加绑定数据,需要跟上面的通配符对应起来QVariantList nameList; //Variant中可以放任意的数据nameList << "aax" << "bbx" << "ccx";query.addBindValue(nameList);QVariantList ageList;ageList << 12 << 13 << 14;query.addBindValue(ageList);//执行批处理query.execBatch();
批处理方式二:
//3.批处理方式二:oracle风格的通配符(更加灵活,推荐)//定义方式: :+自定义名query.prepare("insert into people(name,age) values(:name,:age)");//添加绑定数据,需要跟上面的通配符对应起来QVariantList nameList; //Variant中可以放任意的数据nameList << "aa" << "bb" << "cc";query.bindValue(":name",nameList); //通配符名字,通配符QVariantList ageList;ageList << 11 << 22 << 33;query.bindValue(":age",ageList);//执行批处理query.execBatch();
数据库查询:
//4.数据库查询//4.数据库查询query.exec("select * from people");//如何把返回的值取出来(⭐)while(query.next()) //如果query不为空,(遍历每一条记录){//0 --第一个字段的索引值qDebug()<<query.value(0).toString() //这个0是指exec取出的表中第一个数据类型<<query.value("age").toInt();}// //或者,
// query.exec("select age from people");
// while(query.next()) //如果query不为空,(遍历每一条记录)
// {
// //0 --第一个字段的索引值
// qDebug()<<query.value(0).toInt(); //这样的话此处query.value(0)就为age
// }
3.QSqlTableModel:数据模型。不需要掌握SQL语句,已经在内部做了SQL语句的封装。(创建对象,设置数据库表,将model放入view(QTableView)中,显示(查询)数据,设置表头(setHeadData),setEditStartegy()
//头文件
#include <QSqlTableModel> //数据模型
//显示模型中的数据则需要使用视图:QTableView - QSqlTableModel
// qt中的 model-view模型//前提条件:在步骤1中QSqlDataBase,正常打开数据库
//1.实例化modelmodel = new QSqlTableModel(this);//2.将模型设置到视图中ui->tableView->setModel(model); //在ui中添加//3.给model设置数据库表 -- 前提条件:数据库model->setTable("people");//4.查询表,只有进行查询,model中才会有数据model->select();//设置(更改)表头model->setHeaderData(0,Qt::Horizontal,"编号"); //第一个参数section是字符串截取
需要注意的地方:ui修改自动同步到数据库的风险
//需要注意的是,在ui中修改的话数据库默认也随之更改//5.解决办法:设置提交模式,F1查看函数用法,设置为手动提交,在UI上修改之后需要手动提交DB文件才会进行修改。model->setEditStrategy(QSqlTableModel::OnManualSubmit);.......//在UI中增加一个提交UI修改的按钮,一个撤销的按钮void Widget::on_pushButton_clicked()
{qDebug()<<"on_pushButton_clicked";model->submitAll();
}void Widget::on_pushButton_revent_clicked()
{qDebug()<<"on_pushButton_revent_clicked";model->revertAll(); //撤销步骤model->submitAll(); //提交步骤 --更新数据模型
}
查询数据,此处举例按名字查询,UI上增加输入框和查询按钮
void Widget::on_pushButton_search_clicked()
{qDebug()<<"on_pushButton_revent_clicked";QString name = ui->lineEdit->text(); //获取需要查询的人名//设置过滤条件查询//与SQL语句对比:“select * from aa where name = 'xiaoming'QString sql = QString ("name = '%1'").arg(name);model->setFilter(sql);//重新查询model->select();}