如何在 Repeater 中的 UI QML (QT) 中显示列表中的值
How to display values from lists in a UI QML (QT) inside a Repeater
我已经面对这个问题好几天了,还没有得出结论,希望有人能给我一些有用的提示来解决它。
我将尝试通过示例简化问题:
- 在我的 C++ 代码中,我定义了 class MyObjectModel
稍后作为我主 ui.qml 文件中 Repeater 块中的模型。
MyObjectModel 对 QQmlApplicationEngine 可见。
- MyObjectModel
有 2 个属性(列表):xCoordinatesList 和 yCoordinatesList。
它们表示点列表的 x 和 y 像素坐标。
IE。 xCoordinatesList = [100, 200], yCoordinatesList = [10, 20] 在逻辑上意味着我有 2 个点,我想在屏幕上显示以下像素坐标:(100,10), (10,20).
xCoordinatesList 和 yCoordinatesList 是我模型的角色
QML 引擎。这意味着,例如,在一个共同的
.qml 文件我可以清楚地打印 xCoordinatesList 的内容
输入:
Component.onCompleted
{
console.log("x coordinates: ",xCoordinatesList);
}
问题是:如何在屏幕上同时显示点列表?
如果我只想显示一个点(也就是一对坐标),我的代码就可以工作。我真的不知道如何扩展它以使其打印所有这些。
在我的 MainForm.ui.qml 中,我在 Rectangle[=76= 中定义了一个 Repeater ] :
Rectangle
{
....
Repeater
{
model: dotModel
delegate:
DotItem
{
id: dotItem;
objectName: "dotItem";
DotPositionOnMap
{
id: dotPositionId;
objectWidth: dotItem.width;
objectHeight: dotItem.height;
}
x: dotPositionId.xPositionOnMap;
y: dotPositionId.yPositionOnMap;
}
}
....
}
我需要一个 Repeater,因为 MyObjectModel 包含两个 x 和 y 坐标列表,可以随时间动态变化。
dotModel 只是我用于其他目的的假模型。
DotItem 是我的 qml 项,它标识我想在屏幕上为 xCoordinatesList、yCoordinatesList 中的每对元素描绘的红点圆圈图像。
DotItem.ui.qml
import QtQuick 2.4
import QtQuick.Layouts 1.1
Item
{
width: 10
height: 10
opacity: 1
Image
{
id: dotItemImage
anchors.fill: parent
source: "red_dot.png"
}
}
red_dot.png 屏幕上描绘的每个点都应显示图像。
DotPositionOnMap.qml负责计算右边的x和y像素在屏幕上的位置。
import QtQuick 2.5
import "calcCurrentPos_script.js" as CurrentPos
Item
{
// Values filled from MainForm.ui.qml
property int objectWidth
property int objectHeight
// Getting current coordinates
// Fetching element 0 from both lists
property real currentx: CurrentPos.getCurrentxPoint(0);
property real currenty: CurrentPos.getCurrentyPoint(0);
// Generating the x and y pixel position on map.
// Toy example
property int xPositionOnMap : currentx-(objectWidth/2);
property int yPositionOnMap : currenty-(objectHeight/2);
}
其中calcCurrentPos_script.js
function getCurrentxPoint(val)
{
return xCoordinatesList[val];
}
function getCurrentyPoint(val)
{
return yCoordinatesList[val];
}
这样我只能在屏幕上显示一个点,因为我在 DotPositionOnMap.qml 中指定了要获取的点:
// Fetching element 0 in this case
property real currentx: CurrentPos.getCurrentxPoint(0);
property real currenty: CurrentPos.getCurrentyPoint(0);
我在这次尝试中使用了javascript,因为我认为我可以使用for循环来扫描所有要显示的元素,但它没有用。
我的模型摘录
QVariant MyModelObject::data(const QModelIndex& index, int role) const
{
const MyModelObject& object = objects.values().value(index.row());
....
if(role == XRole)
{
QList<TrackPoint> tkrList = object.getList();
QList<QVariant> tkrVariantList;
for(auto track: trackpointList)
{
tkrVariantList.append(track.getPosition().getX());
}
return QVariant(tkrVariantList);
}
else if(role == YRole)
{
QList<TrackPoint> tkrList = object.getList();
QList<QVariant> tkrVariantList;
for(auto track: trackpointList)
{
tkrVariantList.append(track.getPosition().getY());
}
return QVariant(tkrVariantList);
}
}
....
....
QHash<int, QByteArray> MyModelObject::roleNames() const
{
QHash<int, QByteArray> roles;
roles[XRole] = "xCoordinatesList";
roles[YRole] = "yCoordinatesList";
return roles;
}
我非常感谢任何关于此实现的泛化的想法。
谢谢
Qt 文档非常清楚。您首先要阅读的是 that article. I think that in your case the simpliest way is list-based model. Or, of cource, you can subclass QAbstractListModel.
你的问题不是很清楚,你没有提供模型的代码,但也许这个小例子会对你有所帮助:
声明
class MyModel : public QAbstractListModel
{
Q_OBJECT
public:
enum PointRoles {
XRole = Qt::UserRole + 1,
YRole
};
MyModel(QObject *parent = Q_NULLPTR);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QHash<int, QByteArray> roleNames() const;
private:
QList<QPoint> m_list;
};
实施
MyModel::MyModel(QObject *parent) :
QAbstractListModel(parent)
{
}
QHash<int, QByteArray> MyModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[XRole] = "xcoord";
roles[YRole] = "ycoord";
return roles;
}
int MyModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_list.count();
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if(role == XRole)
return m_list[index.row()].x();
else if(role == YRole)
return m_list[index.row()].y();
return QVariant();
}
报名
qmlRegisterType<MyModel>("qt.test", 1, 0, "PointModel");
用法
Window {
visible: true
width: 800
height: 800
PointModel {id: mymodel}
Repeater {
model: mymodel
delegate: Rectangle {
x: 100 + xcoord
y: 100 + ycoord
width: 20
height: 20
color: "red"
radius: 10
}
}
}
* 已解决 *
在你的main.qml中你可以有这样的东西,它处理全局绘图例程。
Repeater
{
model: dotModel
delegate:
DotPositionOnMap{}
}
DotPositionOnMap.qml 将读取 x 和 y 坐标列表,并为两者的每个元素创建一个点 Item 对象,该对象将显示在屏幕上。
import QtQuick 2.5
Item
{
id: dotPositionOnMap
objectName: "dotoPositionOnMap"
Component.onCompleted:
{
// yCoordinatesList would have given the same result
var dotListLength = xCoordinatesList.length;
// Dot properties can by handled dynamically
var dotWidth = 5;
var dotHeight = 5;
var dotRadius = 10;
var dotColor = "red"
// For each entry of xCoordinatesList and yCoordinatesList
// I generate a DotShape qml object that will display a dot on the screen
for(var i = 0; i < dotListLength; i++)
{
var currentXValue = xCoordinatesList[i];
var currentYValue = yCoordinatesList[i];
// x and y pixrl values for a DotShape.qml instance
var xPositionOnMap = currentXValue-(dotWidth/2);
var yPositionOnMap = currentYValue-(dotHeight/2);
// Creating DotShape.qml component
var comp = Qt.createComponent("DotShape.qml");
var dotComponent = comp.createObject(dotPositionOnMap,
{
"x": xPositionOnMap,
"y": yPositionOnMap,
"width": dotWidth,
"height": dotHeight,
"color": dotColor,
"radius": dotRadius
});
} // end for
} // end script
} // end Item
最后是 DotShape.qml ,它只是在 x,y 坐标
处绘制的一个小红点
import QtQuick 2.5
Rectangle
{
// Other properties are generated at runtime
id: dotShapeId;
objectName: "dotShapeId";
}
我已经面对这个问题好几天了,还没有得出结论,希望有人能给我一些有用的提示来解决它。
我将尝试通过示例简化问题:
- 在我的 C++ 代码中,我定义了 class MyObjectModel 稍后作为我主 ui.qml 文件中 Repeater 块中的模型。 MyObjectModel 对 QQmlApplicationEngine 可见。
- MyObjectModel 有 2 个属性(列表):xCoordinatesList 和 yCoordinatesList。 它们表示点列表的 x 和 y 像素坐标。 IE。 xCoordinatesList = [100, 200], yCoordinatesList = [10, 20] 在逻辑上意味着我有 2 个点,我想在屏幕上显示以下像素坐标:(100,10), (10,20).
xCoordinatesList 和 yCoordinatesList 是我模型的角色 QML 引擎。这意味着,例如,在一个共同的 .qml 文件我可以清楚地打印 xCoordinatesList 的内容 输入:
Component.onCompleted { console.log("x coordinates: ",xCoordinatesList); }
问题是:如何在屏幕上同时显示点列表?
如果我只想显示一个点(也就是一对坐标),我的代码就可以工作。我真的不知道如何扩展它以使其打印所有这些。
在我的 MainForm.ui.qml 中,我在 Rectangle[=76= 中定义了一个 Repeater ] :
Rectangle
{
....
Repeater
{
model: dotModel
delegate:
DotItem
{
id: dotItem;
objectName: "dotItem";
DotPositionOnMap
{
id: dotPositionId;
objectWidth: dotItem.width;
objectHeight: dotItem.height;
}
x: dotPositionId.xPositionOnMap;
y: dotPositionId.yPositionOnMap;
}
}
....
}
我需要一个 Repeater,因为 MyObjectModel 包含两个 x 和 y 坐标列表,可以随时间动态变化。 dotModel 只是我用于其他目的的假模型。 DotItem 是我的 qml 项,它标识我想在屏幕上为 xCoordinatesList、yCoordinatesList 中的每对元素描绘的红点圆圈图像。
DotItem.ui.qml
import QtQuick 2.4
import QtQuick.Layouts 1.1
Item
{
width: 10
height: 10
opacity: 1
Image
{
id: dotItemImage
anchors.fill: parent
source: "red_dot.png"
}
}
red_dot.png 屏幕上描绘的每个点都应显示图像。
DotPositionOnMap.qml负责计算右边的x和y像素在屏幕上的位置。
import QtQuick 2.5
import "calcCurrentPos_script.js" as CurrentPos
Item
{
// Values filled from MainForm.ui.qml
property int objectWidth
property int objectHeight
// Getting current coordinates
// Fetching element 0 from both lists
property real currentx: CurrentPos.getCurrentxPoint(0);
property real currenty: CurrentPos.getCurrentyPoint(0);
// Generating the x and y pixel position on map.
// Toy example
property int xPositionOnMap : currentx-(objectWidth/2);
property int yPositionOnMap : currenty-(objectHeight/2);
}
其中calcCurrentPos_script.js
function getCurrentxPoint(val)
{
return xCoordinatesList[val];
}
function getCurrentyPoint(val)
{
return yCoordinatesList[val];
}
这样我只能在屏幕上显示一个点,因为我在 DotPositionOnMap.qml 中指定了要获取的点:
// Fetching element 0 in this case
property real currentx: CurrentPos.getCurrentxPoint(0);
property real currenty: CurrentPos.getCurrentyPoint(0);
我在这次尝试中使用了javascript,因为我认为我可以使用for循环来扫描所有要显示的元素,但它没有用。
我的模型摘录
QVariant MyModelObject::data(const QModelIndex& index, int role) const
{
const MyModelObject& object = objects.values().value(index.row());
....
if(role == XRole)
{
QList<TrackPoint> tkrList = object.getList();
QList<QVariant> tkrVariantList;
for(auto track: trackpointList)
{
tkrVariantList.append(track.getPosition().getX());
}
return QVariant(tkrVariantList);
}
else if(role == YRole)
{
QList<TrackPoint> tkrList = object.getList();
QList<QVariant> tkrVariantList;
for(auto track: trackpointList)
{
tkrVariantList.append(track.getPosition().getY());
}
return QVariant(tkrVariantList);
}
}
....
....
QHash<int, QByteArray> MyModelObject::roleNames() const
{
QHash<int, QByteArray> roles;
roles[XRole] = "xCoordinatesList";
roles[YRole] = "yCoordinatesList";
return roles;
}
我非常感谢任何关于此实现的泛化的想法。
谢谢
Qt 文档非常清楚。您首先要阅读的是 that article. I think that in your case the simpliest way is list-based model. Or, of cource, you can subclass QAbstractListModel.
你的问题不是很清楚,你没有提供模型的代码,但也许这个小例子会对你有所帮助:
声明
class MyModel : public QAbstractListModel
{
Q_OBJECT
public:
enum PointRoles {
XRole = Qt::UserRole + 1,
YRole
};
MyModel(QObject *parent = Q_NULLPTR);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QHash<int, QByteArray> roleNames() const;
private:
QList<QPoint> m_list;
};
实施
MyModel::MyModel(QObject *parent) :
QAbstractListModel(parent)
{
}
QHash<int, QByteArray> MyModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[XRole] = "xcoord";
roles[YRole] = "ycoord";
return roles;
}
int MyModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_list.count();
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
if(role == XRole)
return m_list[index.row()].x();
else if(role == YRole)
return m_list[index.row()].y();
return QVariant();
}
报名
qmlRegisterType<MyModel>("qt.test", 1, 0, "PointModel");
用法
Window {
visible: true
width: 800
height: 800
PointModel {id: mymodel}
Repeater {
model: mymodel
delegate: Rectangle {
x: 100 + xcoord
y: 100 + ycoord
width: 20
height: 20
color: "red"
radius: 10
}
}
}
* 已解决 *
在你的main.qml中你可以有这样的东西,它处理全局绘图例程。
Repeater
{
model: dotModel
delegate:
DotPositionOnMap{}
}
DotPositionOnMap.qml 将读取 x 和 y 坐标列表,并为两者的每个元素创建一个点 Item 对象,该对象将显示在屏幕上。
import QtQuick 2.5
Item
{
id: dotPositionOnMap
objectName: "dotoPositionOnMap"
Component.onCompleted:
{
// yCoordinatesList would have given the same result
var dotListLength = xCoordinatesList.length;
// Dot properties can by handled dynamically
var dotWidth = 5;
var dotHeight = 5;
var dotRadius = 10;
var dotColor = "red"
// For each entry of xCoordinatesList and yCoordinatesList
// I generate a DotShape qml object that will display a dot on the screen
for(var i = 0; i < dotListLength; i++)
{
var currentXValue = xCoordinatesList[i];
var currentYValue = yCoordinatesList[i];
// x and y pixrl values for a DotShape.qml instance
var xPositionOnMap = currentXValue-(dotWidth/2);
var yPositionOnMap = currentYValue-(dotHeight/2);
// Creating DotShape.qml component
var comp = Qt.createComponent("DotShape.qml");
var dotComponent = comp.createObject(dotPositionOnMap,
{
"x": xPositionOnMap,
"y": yPositionOnMap,
"width": dotWidth,
"height": dotHeight,
"color": dotColor,
"radius": dotRadius
});
} // end for
} // end script
} // end Item
最后是 DotShape.qml ,它只是在 x,y 坐标
处绘制的一个小红点import QtQuick 2.5
Rectangle
{
// Other properties are generated at runtime
id: dotShapeId;
objectName: "dotShapeId";
}