我几天都在努力想弄清楚如何在QML窗口中显示一些非常简单的数据。我意识到有很多方法可以完成这项任务,在这种情况下,我更愿意了解如何使用QAbstractTableModel。
我有一行数据,每行包含两个项目,一个名称和一个值(名称/值或键/值对)。我已将QAbstractTableModel子类化,以将此数据传递给QML。这是我到目前为止的代码;它主要基于可以在这里找到的教程(也很老):https://doc.qt.io/archives/4.6/itemviews-addressbook.html。
#include <QObject>
#include <QAbstractTableModel>
#include <QPair>
class DataBridge : public QAbstractTableModel
{
Q_OBJECT
public:
explicit DataBridge();
explicit DataBridge(QList<QPair<QString, QString>> listOfPairs);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
bool insertRows(int row, int count, const QModelIndex &parent);
bool removeRows(int row, int count, const QModelIndex &parent);
Qt::ItemFlags flags(const QModelIndex &index) const;
QList<QPair<QString, QString>> getList();
signals:
public slots:
private:
QList<QPair<QString, QString>> m_listOfPairs;
};
#endif // DATABRIDGE_H
#include "databridge.h"
DataBridge::DataBridge()
{}
DataBridge::DataBridge(QList<QPair<QString, QString> > listOfPairs)
{ m_listOfPairs = listOfPairs; }
int DataBridge::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_listOfPairs.size();
}
int DataBridge::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
//Number of columns is always 2 in this kata
return 2;
}
QVariant DataBridge::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();
if(index.row() >= m_listOfPairs.size() || index.row() < 0)
return QVariant();
if(role == Qt::DisplayRole)
{
QPair<QString, QString> pair = m_listOfPairs.at(index.row());
if(index.column() == 0)
return pair.first;
else
return pair.second;
}
return QVariant();
}
bool DataBridge::setData(const QModelIndex &index, const QVariant &value, int role)
{
//TODO
return QVariant();
}
QVariant DataBridge::headerData(int section, Qt::Orientation orientation, int role) const
{
//TODO
return QVariant();
}
bool DataBridge::insertRows(int row, int count, const QModelIndex &parent)
{
//TODO
return true;
}
bool DataBridge::removeRows(int row, int count, const QModelIndex &parent)
{
//TODO
return true;
}
Qt::ItemFlags DataBridge::flags(const QModelIndex &index) const
{
if(!index.isValid())
return Qt::ItemIsEnabled;
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}
QList<QPair<QString, QString> > DataBridge::getList()
{
return m_listOfPairs;
}
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QPair>
#include "databridge.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QList<QPair<QString, QString>> inserter;
inserter.append(QPair<QString, QString>("0", "zero"));
inserter.append(QPair<QString, QString>("1", "one"));
inserter.append(QPair<QString, QString>("2", "two"));
inserter.append(QPair<QString, QString>("3", "three"));
inserter.append(QPair<QString, QString>("4", "four"));
DataBridge * bridge = new DataBridge(inserter);
engine.rootContext()->setContextProperty("bridge", bridge);
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component{
id: myComponent
Row{
id: thisRow
Text{
text: bridge.data(index, 0)
}
Text{
text: "\t.\t.\t.\t"
}
Text{
text: bridge.data(index, 0)
}
}
}
Column{
id: thisColumn
anchors.horizontalCenter: parent.horizontalCenter
Repeater{
id: myRepeater
delegate: myComponent
model: bridge
}
}
Component.onCompleted: {
console.log("DEBUG main.qml");
}
}
请在databridge.cpp中忽略其中包含TODO的功能。为了简洁起见,我没有包括尸体。
我面临的第一个问题是,当main.qml中的转发器调用bridge.data(index,0)时,在数据函数的第一个if语句中确定索引无效(如果(!index.isValid())。我不确定为什么会发生这种情况。我能看到的第二个问题,虽然我还没有达到这个目的,但是如果我和我怎么能告诉数据功能呢? #39; m调用第0列还是第1列?它稍后在函数中检查它,并返回与所请求的列相关的对。我猜测在myComponent中,我需要更具体的东西来请求来自无论哪一列,但我不确定那会是什么?
对此的任何帮助都将非常感激。提前谢谢!
Another link to the example referenced at the top
答案 0 :(得分:0)
我能够找到解决方案,但我不确定它是否正确。我在databridge类中添加了一个函数,该函数从QML获取整数输入,找到相应的QModelIndex,然后以这种方式从模型中提取数据。这就是代码的样子:
QString DataBridge::getThisItem(int index, int column)
{
QModelIndex currentIndex = QAbstractTableModel::index(index, column);
QString retVal = data(currentIndex, 0).toString();
return retVal;
}
Component{
id: myComponent
Row{
id: thisRow
Text{
text: bridge.getThisItem(index, 0)
}
Text{
text: "\t.\t.\t.\t"
}
Text{
text: bridge.getThisItem(index, 1)
}
}
}
我很想知道这是一个很好的实现,还是有更好的方法来实现这一点。再次感谢!