c++ - QSqlTableModel 到 qml 列表多次出现
问题描述
我是新手,正在尝试学习 qt 和 qml,但我找不到解决这个问题的方法。
我有一个只有 4 行测试数据的 QSqlTableModel,但我想将 1 列(其中只有 1 个值)中的不同值转换为 qml ListModel 的列表。
我Q_PROPERTY(QStringList distinctSemesters READ getSemesterList NOTIFY semesterChanged)
在我的 SqlDataModel.h 文件中有这个,在我的 sqldatamodel.cpp 中有这个
QStringList SqlDataModel::getSemesterList() const
{
QStringList mySemesters;
QSqlQuery query;
query.exec("SELECT DISTINCT Semester FROM results");
while (query.next()) {
QString currentSemester = query.value(0).toString();
mySemesters << currentSemester;
}
return mySemesters;
}
它返回一个长度为 1 的 QStringList。我正在尝试将其读入我的 qml
ListView {
model: SqlDataModel {
id: myModel
}
delegate: ItemDelegate {
width: parent.width
text: myModel.distinctSemesters
}
}
这适用于从 getSemesterList() 函数获取字符串。但是字符串在列表视图中重复了 4 次(我的表模型的大小)。我已经检查了这一点并在测试表中添加了更多行,这在我的列表视图中继续重复相同的字符串更多次。
根据我有限的理解,我猜这将永远是这种情况,因为列表视图从模型中获取它的大小 - 这是 qsl 表的大小。我不知道该怎么做,其他人可以指出我正确的方向吗?
我目前的想法是创建一个新的 sqlmodel 以引入 qml(但我需要读+写,所以我相信 sqltablemodel 对此有好处),或者我应该尝试用 javascript 修复 qml 方面。我在 javascript 中查看了它,但是当我尝试时
property ListModel distinctSemesters;
Component.onCompleted: {
console.log(distinctSemesters)
我不断收到不同学期未定义的错误。
非常感谢您的任何帮助。
下面(我希望)是一个可重复的例子。我使用了一些在线资源来指导这一点。主.cpp:
int main(int argc, char *argv[])
{
initDatabase();
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
qmlRegisterType<SqlDataModel>("GradesSqlDataModel", 1, 0, "SqlDataModel");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
SqlDataModel.h
class SqlDataModel : public QSqlTableModel
{
Q_OBJECT
Q_PROPERTY(QString semester READ getsemester WRITE setSemester NOTIFY semesterChanged)
Q_PROPERTY(QStringList distinctSemesters READ getSemesterList NOTIFY semesterChanged)
public:
SqlDataModel(QObject *parent = 0);
QStringList getSemesterList() const;
QString getsemester() const;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
signals:
void semesterChanged();
};
SqlDataModel.cpp
SqlDataModel::SqlDataModel(QObject *parent) :
QSqlTableModel(parent)
{
createTable();
setTable("Results");
setEditStrategy(QSqlTableModel::OnManualSubmit);
select();
}
QStringList SqlDataModel::getSemesterList() const
{
QStringList mySemesters;
QSqlQuery query;
query.exec("SELECT DISTINCT Semester FROM results");
while (query.next()) {
QString currentSemester = query.value(0).toString();
mySemesters << currentSemester;
qDebug() << currentSemester;
}
qDebug() << "length :" <<mySemesters.length();
return mySemesters;
}
QHash<int, QByteArray> SqlDataModel::roleNames() const
{
QHash<int, QByteArray> dataNames;
dataNames[Qt::UserRole] = "ID";
dataNames[Qt::UserRole + 1] = "Semester";
dataNames[Qt::UserRole + 2] = "CourseTitle";
dataNames[Qt::UserRole + 3] = "TestWeight";
dataNames[Qt::UserRole + 4] = "TestName";
dataNames[Qt::UserRole + 5] = "Result";
dataNames[Qt::UserRole + 6] = "OutOf";
qDebug() << "DataNames" << dataNames;
return dataNames;
}
QVariant SqlDataModel::data(const QModelIndex &index, int role) const
{
qDebug() << "settingData";
if (role < Qt::UserRole)
return QSqlTableModel::data(index, role);
const QSqlRecord sqlRecord = record(index.row());
return sqlRecord.value(role - Qt::UserRole);
}
main.qml
ApplicationWindow {
id: window;
visible: true;
width: 640;
height: 600;
title: qsTr("TEST")
Drawer {
id: drawer
width: Math.min(window.width, window.height) / 3 * 2
height: window.height
interactive: true
ListView {
model: SqlDataModel {
id: myModel
}
delegate: ItemDelegate {
width: parent.width
text: myModel.distinctSemesters
}
}
}
我的结果 sql 表看起来像这样(只有一个 ID 主键在前):
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 1', '10', 'Exam 1', 50, 100)");
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 1', '33', 'Exam 2', 70, 100)");
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 2', '25', 'Exam 1', 0, 100)");
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 2', '5', 'Quiz 1', 5, 20)");
解决方案
解释:
在您的情况下,QSqlTableModel 加载表的所有行,因为没有过滤器,因此它将有 4 行,因此使用它的任何视图也将显示这 4 行,因此 ListView 显示 4 行。为什么每一行显示相同的信息?好吧,因为在每个项目中,您都让代表展示了始终是“2020 年春季”的不同“学期”。
解决方案:
在这种情况下,没有必要使用 QSqlTableModel,因为 QSqlQueryModel 足以允许从 QML 进行过滤,因此您可以使用我的其他答案的模型。因此,只需将其导出到 QML 并使用它就足够了。
qmlRegisterType<SqlQueryModel>("GradesSqlDataModel", 1, 0, "SqlQueryModel");
import QtQuick 2.14
import QtQuick.Window 2.14
import QtQuick.Controls 2.14
import GradesSqlDataModel 1.0
Window {
id: window
visible: true
width: 640;
height: 600;
SqlQueryModel{
id: sqlquerymodel
query: "SELECT DISTINCT Semester FROM results"
}
Drawer {
id: drawer
width: Math.min(window.width, window.height) / 3 * 2
height: window.height
interactive: true
ListView{
anchors.fill: parent
model: sqlquerymodel
delegate: ItemDelegate {
width: parent.width
text: model.Semester
}
}
}
Component.onCompleted: drawer.visible = true
}
完整的例子可以在这里找到。
推荐阅读
- python - 如何使用包和网格布局将可滚动框架中的所有元素水平居中
- selected - 垫子自动完成选定的值
- microsoft-teams - 具有嵌入式 Web 视图的 Teams 消息传递扩展 - Web 应用程序的结构
- css - 防止 Chrome 浏览器将位置属性转换为插入
- python - 为什么我的数据框没有附加到迭代中?
- javascript - 如何防止Angular自动导航到页面中间
- r - 以一列为基础制作列
- spring-boot - Gradle 测试因没有版本的依赖而失败
- c - C如何将数组中的ASCII数字转换为文本
- vue.js - 导入 vue 模板片段导致 [Object Promise]