我正在用qml和qt5编写一个小代码。
代码正在从sqlite db中读取记录(> 1000条记录)并显示 列表视图上的记录。代码本身正如我所预期的那样工作,但我想要更加响应地改进UI。
在当前阶段,当我按下获取记录的按钮时,查询按钮很长时间(大约4分钟)已经死亡。 所以我想让代码运行另一个从sqlite db收集记录并更新listview的线程。 同时,我想在收集记录时显示busyindicator。
我研究了关于线程的qml和qt5,但很难理解如何应用于listmodel。目前,我不是根据qml提示考虑工人。
如果有人能用我的代码向我展示一些实现,我将不胜感激:
的main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QDir>
#include <QQmlContext>
#include <QStandardItemModel>
#include "DBObject.h"
#include "EnvironmentModel.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
EnvironmentModel* model = new EnvironmentModel;
ctxt->setContextProperty("environmentModel", model);
DBObject* DB = new DBObject;
DB->setEnvironmentModel(model);
ctxt->setContextProperty("DB", DB);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml
import QtQuick 2.10
import QtQuick.Controls 2.3
import "listView"
ApplicationWindow {
id: mainWindow
visible: true
width: 740
height: 640
title: qsTr("DB query")
Page1 {
id: page1
}
}
page1.qml
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Dialogs 1.3
import "listView"
Item {
id: page1
anchors.fill: parent
readonly property int margin: 10
Button {
text: "Query"
onClicked: {
DB.registerCoordinate(78, 124);
DB.setYearRange(1979, 1980);
popup.open()
}
}
}
Popup {
id: popup
x: 1
y: 1
width: parent.width
height: parent.height
modal: true
focus: true
visible: false
onVisibleChanged: {
DB.query()
}
Rectangle {
id: titleBar
width: parent.width
height: 20
color: "#bebebe"
Row {
spacing: 10
Text { width: 100; text: "Index"; horizontalAlignment: Text.AlignHCenter }
Text { width: 100; text: "Date"; horizontalAlignment: Text.AlignHCenter }
Text { width: 100; text: "Time"; horizontalAlignment: Text.AlignHCenter }
Text { width: 100; text: "Hs"; horizontalAlignment: Text.AlignHCenter }
Text { width: 100; text: "Tp"; horizontalAlignment: Text.AlignHCenter }
Text { width: 100; text: "Dp"; horizontalAlignment: Text.AlignHCenter }
Text { width: 100; text: "Vw"; horizontalAlignment: Text.AlignHCenter }
Text { width: 100; text: "Dw"; horizontalAlignment: Text.AlignHCenter }
}
}
Page2 {
id: resultWindow
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.rightMargin: 10
anchors.top: titleBar.bottom
anchors.topMargin: 10
anchors.bottom:bottomBar.top
anchors.bottomMargin: 10
}
closePolicy: Popup.CloseOnEscape
}
}
page2.qml
import QtQuick 2.10
import QtQuick.Controls 2.3
import "listView"
Item {
id: page2
EnvironmentList {
height:200
width: parent.width
}
}
EnvironmentList.qml
import QtQuick 2.10
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.0
import QtLocation 5.6
import QtPositioning 5.6
Rectangle {
id: container
anchors.fill: parent
Component {
id: environmentDelegate
Row {
spacing: 10
Text { width: 100; text: index+1; horizontalAlignment: Text.AlignHCenter}
Text { width: 100; text: date; horizontalAlignment: Text.AlignHCenter}
Text { width: 100; text: time; horizontalAlignment: Text.AlignHCenter}
Text { width: 100; text: hs.toFixed(2); horizontalAlignment: Text.AlignHCenter}
Text { width: 100; text: tp.toFixed(2); horizontalAlignment: Text.AlignHCenter}
Text { width: 100; text: dp.toFixed(2); horizontalAlignment: Text.AlignHCenter}
Text { width: 100; text: vw.toFixed(2); horizontalAlignment: Text.AlignHCenter}
Text { width: 100; text: dw.toFixed(2); horizontalAlignment: Text.AlignHCenter}
}
}
ListView {
id: environmentList
anchors.fill: parent
model: environmentModel
delegate: environmentDelegate
flickableDirection: Flickable.VerticalFlick
boundsBehavior: Flickable.StopAtBounds
ScrollBar.vertical: ScrollBar {}
}
}
EnvironmentModel.h
#ifndef ENVIRONMENTMODEL_H
#define ENVIRONMENTMODEL_H
#include <QQuickView>
#include <QQmlContext>
#include <QStandardItemModel>
class EnvironmentModel : public QStandardItemModel
{
Q_OBJECT
public:
EnvironmentModel() : QStandardItemModel()
{
QHash<int, QByteArray> roleNames;
roleNames[Qt::UserRole + 1] = "date";
roleNames[Qt::UserRole + 2] = "time";
roleNames[Qt::UserRole + 3] = "lat";
roleNames[Qt::UserRole + 4] = "lon";
roleNames[Qt::UserRole + 5] = "hs";
roleNames[Qt::UserRole + 6] = "tp";
roleNames[Qt::UserRole + 7] = "dp";
roleNames[Qt::UserRole + 8] = "vw";
roleNames[Qt::UserRole + 9] = "dw";
this->setItemRoleNames(roleNames);
}
Q_INVOKABLE void writeToCSV(const QString& path);
};
#endif /* ENVIRONMENTMODEL_H */
DBObject.h
#ifndef DBOBJECT_H
#define DBOBJECT_H
#include <QObject>
#include <vector>
#include "DB.h"
#include "EnvironmentModel.h"
class DBObject : public QObject
{
Q_OBJECT
public:
explicit DBObject(QObject* parent = 0);
public:
void setEnvironmentModel(EnvironmentModel* model);
Q_INVOKABLE void registerCoordinate(float lat, float lon);
Q_INVOKABLE void setYearRange(unsigned yearStart, unsigned yearEnd);
Q_INVOKABLE void query();
private:
DB db_;
EnvironmentModel* model_;
unsigned yearStart_;
unsigned yearEnd_;
std::vector<float> lats_;
std::vector<float> lons_;
};
#endif /* DBOBJECT_H */
DBObject.cpp
#include <QDebug>
#include <QDir>
#include "DBObject.h"
DBObject::DBObject(QObject* parent)
: QObject(parent)
{}
void DBObject::setEnvironmentModel(EnvironmentModel* model) {
model_ = model;
}
void DBObject::registerCoordinate(float lat, float lon) {
lons_.push_back(lon);
lats_.push_back(lat);
}
void DBObject::setYearRange(unsigned yearStart, unsigned yearEnd) {
yearStart_ = yearStart;
yearEnd_ = yearEnd;
}
void DBObject::query()
{
for (auto i=0U; i<lats_.size(); ++i)
{
std::list<DB::Record> records = db_.query(yearStart_, yearEnd_, lons_[i], lats_[i]);
for(auto iter=records.begin(); iter!=records.end(); ++iter)
{
QList<QStandardItem*> columnItems;
QStandardItem *item = new QStandardItem();
item->setData(iter->date_, Qt::UserRole + 1);
item->setData(iter->time_, Qt::UserRole + 2);
item->setData(iter->lat_, Qt::UserRole + 3);
item->setData(iter->lon_, Qt::UserRole + 4);
item->setData(iter->hs_, Qt::UserRole + 5);
item->setData(iter->tp_, Qt::UserRole + 6);
item->setData(iter->dp_, Qt::UserRole + 7);
item->setData(iter->vw_, Qt::UserRole + 8);
item->setData(iter->dw_, Qt::UserRole + 9);
columnItems << item;
model_->appendRow( columnItems );
}
}
}
答案 0 :(得分:1)
没有测试:
我想,你的问题在于这些方面:
for (auto i=0U; i<lats_.size(); ++i)
{
std::list<DB::Record> records = db_.query(yearStart_, yearEnd_, lons_[i], lats_[i]);
for(auto iter=records.begin(); iter!=records.end(); ++iter)
{
QList<QStandardItem*> columnItems;
QStandardItem *item = new QStandardItem();
item->setData(iter->date_, Qt::UserRole + 1);
item->setData(iter->time_, Qt::UserRole + 2);
item->setData(iter->lat_, Qt::UserRole + 3);
item->setData(iter->lon_, Qt::UserRole + 4);
item->setData(iter->hs_, Qt::UserRole + 5);
item->setData(iter->tp_, Qt::UserRole + 6);
item->setData(iter->dp_, Qt::UserRole + 7);
item->setData(iter->vw_, Qt::UserRole + 8);
item->setData(iter->dw_, Qt::UserRole + 9);
columnItems << item;
model_->appendRow( columnItems );
}
}
它的作用是,它多次将单个项目的列表附加到模型中。 每次调用都会触发一个信号到视图,以刷新视图。
相反,您应首先获取所有columnItem的完整列表,然后立即将数据推送到模型。
答案 1 :(得分:0)
您应该阅读QFutureWatcher
并查看是否可以解决您的问题。有关如何组合SQListe和Futures的示例。