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

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

本文关键字:QT 显示 列表 QML Repeater 内部 UI      更新时间:2023-10-16

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

我将试着用一个例子来简化这个问题:

    在我的c++代码中,我定义了将起作用的类MyObjectModel稍后在我的主ui中的Repeater块中作为模型。qml 文件。MyObjectModel对QQmlApplicationEngine可见。
  • MyObjectModel 有两个属性(列表):xCoordinatesList和yCoordinatesList。它们表示点列表的x和y像素坐标。即xCoordinatesList = [100,200], yCoordinatesList =[10,20]在逻辑上意味着我有2个点,我想在屏幕上显示以下像素坐标:(100,10),(10,20)。
  • xCoordinatesList和yCoordinatesList是我模型的Roles用于QML引擎。这意味着,例如,在一个共同的.qml文件可以清楚地打印xCoordinatesList的内容输入:

    Component.onCompleted
    {
        console.log("x coordinates: ",xCoordinatesList);
    }
    

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

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

在我的MainForm.ui。qml我定义了一个中继器矩形:

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

我需要一个中继器,因为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文档非常清楚。你首先要读的是那篇文章。我认为在你的情况下,最简单的方法是基于列表的模型。当然,您也可以创建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();
}

Registation

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

* SOLVED *

主目录中。qml你可以有这样的东西,它处理全局绘图例程。

    Repeater
    {
        model: dotModel
        delegate:
        DotPositionOnMap{}
    }

DotPositionOnMap。qml将读取x和y坐标列表,并为两者的每个元素创建一个dot 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";
}