如何在 Repeater 中的 UI QML (QT) 中显示列表中的值

How to display values from lists in a UI QML (QT) inside a Repeater

我已经面对这个问题好几天了,还没有得出结论,希望有人能给我一些有用的提示来解决它。

我将尝试通过示例简化问题:

问题是:如何在屏幕上同时显示点列表?

如果我只想显示一个点(也就是一对坐标),我的代码就可以工作。我真的不知道如何扩展它以使其打印所有这些。

在我的 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负责计算右边的xy像素在屏幕上的位置。

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";
}