如何将 Qt 的 SQL 查询输出模型分配给 QML 的 TableView?
How to assign SQL query output model from Qt to QML's TableView?
来自 C++ (Qt):
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
/*
* I have omitted the code about connection with the database and all for ease of
* viewing the code.
*/
// My own function for filling in the data in the `QSqlQueryModel`
QSqlQueryModel* model = new QSqlQueryModel;
QString binid = "B1";
QString query = "SELECT t1.BinId, t1.PartitionId, t2.UnitId, t2.ItemCount FROM Bin_Partitions AS t1 "
"INNER JOIN Partition_Units AS t2 ON t1.PartitionId = t2.PartitionId "
"WHERE t1.BinId ='" + binid + "'";
model->setQuery(query);
/*
* I can see that the query runs successfully because the following
* QTableView DOES get populated properly.
*/
// Use QTableView to visualize
QTableView *view = new QTableView;
view->setModel(model);
view->show();
QQmlApplicationEngine engine;
// Passing the same model to QML for displaying in the TableView.
engine.rootContext()->setContextProperty ("SQQL", model);
engine.load(QUrl(QStringLiteral("/home/.../main.qml")));
QObject *topLevel = engine.rootObjects ().value (0);
QQuickWindow *window = qobject_cast <QQuickWindow *> (topLevel);
return app.exec();
}
来自 QML:
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
Window
{
visible: true
width: 360
height: 360
color: "blue"
TableView
{
TableViewColumn{ role: "col1" ; title: "BinId" ; visible: true}
TableViewColumn{ role: "col2" ; title: "PartitionId" }
TableViewColumn{ role: "col3" ; title: "UnitId" }
TableViewColumn{ role: "col4" ; title: "ItemCount" }
model: SQQL
}
}
QML 的 TableView 显示为 EMPTY!
我需要帮助。
您必须继承 QSqlQueryModel
并重新实现 roleNames
和 data
方法
MySqlModel.h
class MySqlModel: public QSqlQueryModel
{
Q_OBJECT
public:
MySqlModel(QObject *parent = 0) : QSqlQueryModel(parent) {}
enum Roles {
BinId = Qt::UserRole + 1,
PartitionId,
UnitId,
ItemCount
};
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[BinId] = "binIdRole";
roles[PartitionId] = "partitionIdRole";
roles[UnitId] = "unitIdRole";
roles[ItemCount] = "itemCountRole";
return roles;
}
QVariant data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
QString fieldName;
switch (role) {
case BinId: fieldName = QStringLiteral("t1.BinId"); break;
case PartitionId: fieldName = QStringLiteral("t1.PartitionId"); break;
case UnitId: fieldName = QStringLiteral("t2.UnitId"); break;
case ItemCount: fieldName = QStringLiteral("t2.ItemCount"); break;
}
if (!this->record().isGenerated(fieldName))
return QVariant();
else {
QModelIndex item = indexInQuery(index);
if ( !this->query().seek(item.row()) )
return QVariant();
return this->query().value(fieldName);
}
return QVariant();
}
};
main.qml
Window {
visible: true
width: 640
height: 480
TableView {
anchors.fill: parent
model: SQQL
TableViewColumn{ role: "binIdRole" ; title: "BinId" ; visible: true}
TableViewColumn{ role: "partitionIdRole" ; title: "PartitionId" }
TableViewColumn{ role: "unitIdRole" ; title: "UnitId" }
TableViewColumn{ role: "itemCountRole" ; title: "ItemCount" }
}
}
来自 C++ (Qt):
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
/*
* I have omitted the code about connection with the database and all for ease of
* viewing the code.
*/
// My own function for filling in the data in the `QSqlQueryModel`
QSqlQueryModel* model = new QSqlQueryModel;
QString binid = "B1";
QString query = "SELECT t1.BinId, t1.PartitionId, t2.UnitId, t2.ItemCount FROM Bin_Partitions AS t1 "
"INNER JOIN Partition_Units AS t2 ON t1.PartitionId = t2.PartitionId "
"WHERE t1.BinId ='" + binid + "'";
model->setQuery(query);
/*
* I can see that the query runs successfully because the following
* QTableView DOES get populated properly.
*/
// Use QTableView to visualize
QTableView *view = new QTableView;
view->setModel(model);
view->show();
QQmlApplicationEngine engine;
// Passing the same model to QML for displaying in the TableView.
engine.rootContext()->setContextProperty ("SQQL", model);
engine.load(QUrl(QStringLiteral("/home/.../main.qml")));
QObject *topLevel = engine.rootObjects ().value (0);
QQuickWindow *window = qobject_cast <QQuickWindow *> (topLevel);
return app.exec();
}
来自 QML:
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
Window
{
visible: true
width: 360
height: 360
color: "blue"
TableView
{
TableViewColumn{ role: "col1" ; title: "BinId" ; visible: true}
TableViewColumn{ role: "col2" ; title: "PartitionId" }
TableViewColumn{ role: "col3" ; title: "UnitId" }
TableViewColumn{ role: "col4" ; title: "ItemCount" }
model: SQQL
}
}
QML 的 TableView 显示为 EMPTY!
我需要帮助。
您必须继承 QSqlQueryModel
并重新实现 roleNames
和 data
方法
MySqlModel.h
class MySqlModel: public QSqlQueryModel
{
Q_OBJECT
public:
MySqlModel(QObject *parent = 0) : QSqlQueryModel(parent) {}
enum Roles {
BinId = Qt::UserRole + 1,
PartitionId,
UnitId,
ItemCount
};
QHash<int, QByteArray> roleNames() const {
QHash<int, QByteArray> roles;
roles[BinId] = "binIdRole";
roles[PartitionId] = "partitionIdRole";
roles[UnitId] = "unitIdRole";
roles[ItemCount] = "itemCountRole";
return roles;
}
QVariant data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
QString fieldName;
switch (role) {
case BinId: fieldName = QStringLiteral("t1.BinId"); break;
case PartitionId: fieldName = QStringLiteral("t1.PartitionId"); break;
case UnitId: fieldName = QStringLiteral("t2.UnitId"); break;
case ItemCount: fieldName = QStringLiteral("t2.ItemCount"); break;
}
if (!this->record().isGenerated(fieldName))
return QVariant();
else {
QModelIndex item = indexInQuery(index);
if ( !this->query().seek(item.row()) )
return QVariant();
return this->query().value(fieldName);
}
return QVariant();
}
};
main.qml
Window {
visible: true
width: 640
height: 480
TableView {
anchors.fill: parent
model: SQQL
TableViewColumn{ role: "binIdRole" ; title: "BinId" ; visible: true}
TableViewColumn{ role: "partitionIdRole" ; title: "PartitionId" }
TableViewColumn{ role: "unitIdRole" ; title: "UnitId" }
TableViewColumn{ role: "itemCountRole" ; title: "ItemCount" }
}
}