首页 文章

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

提问于
浏览
0

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

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

  • 在我的C代码中,我定义了类 MyObjectModel ,它稍后将作为我的主ui.qml文件中 Repeater 块中的模型 . MyObjectModel对QQmlApplicationEngine可见 .

  • MyObjectModel 有2个属性(列表):xCoordinatesList和yCoordinatesList . 它们代表点列表的x和y像素坐标 . 即xCoordinatesList = [100,200],yCoordinatesList = [10,20]在逻辑上意味着我有2个点,我想在屏幕上显示以下像素坐标:(100,10),(10,20) .

  • xCoordinatesList和yCoordinatesList是我的 QML engine 模型的 Roles . 这意味着,例如,在一个常见的.qml文件中,我可以通过输入以下内容清楚地打印xCoordinatesList的内容:

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

The question is: how can I display at the same time the list of points on the screen?

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

在我 MainForm.ui.qml 中我在 Rectangle 中定义了 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 中指定了指向fetch:

// Fetching element 0 in this case
property real currentx: CurrentPos.getCurrentxPoint(0);
property real currenty: CurrentPos.getCurrentyPoint(0);

我使用javascript进行此尝试,因为我认为我可以使用for循环来扫描要显示的所有元素,但它不起作用 .

Extract of my model

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

我非常感谢有关此实现的概括的任何想法 .

谢谢

2 回答

  • 0

    Qt文档非常清楚 . 你需要阅读的第一个是that article . 我认为在你的情况下,最简单的方法是list-based model . 或者,对于cource,您可以继承QAbstractListModel .

    你的问题不是那么清楚,你没有提供你的模型的代码,但也许这个小例子可以帮助你:

    Declaration

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

    Implementation

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

    Usage

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

    *** SOLVED ***

    main.qml 中你可以有类似的东西,它处理全局绘图程序 .

    Repeater
        {
            model: dotModel
            delegate:
            DotPositionOnMap{}
        }
    

    DotPositionOnMap.qml 将读取x和y坐标列表,并且对于两者的每个元素将创建一个点项目对象,该对象将显示在屏幕上 .

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

相关问题