массив в python, отображаемый с использованием элементов в qml - PullRequest
1 голос
/ 17 октября 2019

Я должен отобразить некоторые текты с qml. Эти Rectangle {} положительные из них зависят от x = array [i] [0] и y = array [i] [1], а их количество зависит от array.lenght ().

массив в qml должен быть равен self .__ rectanglePos в Python

Поэтому мне нужен способ нарисовать Rectangle в другой позиции и в другом количестве, которое зависит от массива.

как я могу это сделать?

_____. Py

class NN(QObject):
    def __init__(self):
        QObject.__init__(self)
        self.__rectanglePos = [] #each element contains:[x,y,orientation 360°]

    #signals
    rectanglePosChanged = Signal(type(self.__rectanglePos))

    @Slot()
    def rects(self):   
        self.rectanglePosChanged.emit(self.__rectanglePos)   


if __name__ == '__main__':
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    qmlRegisterType(NN, 'gnn', 1, 0, 'NN')
    engine.load(QUrl.fromLocalFile(gnn.qml))
    if not engine.rootObjects():
        sys.exit(-1)   
    sys.exit(app.exec_())

это не работает в qml: ________. Qml

#[...]
import gnn 1.0


ApplicationWindow {
     ListView{
            id: rect
            function f(){
                for (var i = 0; i < array.lenght(); ++i){
                     Rectangle {      
                          x: array[i][0]
                          y: array[i][1]
                     }
                }                  
            }
    }
    MouseArea{
    onClicked: rects()
    }
    NN{
        id: nn

        signal getRectangles(var array) // not working

        Component.onCompleted: {

            nn.rectanglePosChanged.connect(getRectangles)

        }
    }
    Connections {
        target: nn

        onGetRectangles: {

        }

    }
}

1 Ответ

0 голосов
/ 21 октября 2019

В вашем коде много ошибок, например, вы хотите получить доступ к атрибуту класса: self.__rectanglePos), который имеет смысл только при создании объекта из части кода, которая выполняется перед созданием класса: rectanglePosChanged = Signal(type(self.__rectanglePos)),поэтому я не буду указывать, какие у вас ошибки, кроме тех, которые необходимы для моего решения.

Если вы хотите отправить информацию в виде списка, куда вы добавляете, заменяете или удаляете элементы, то лучше использовать модель какуведомит вас с учетом изменений. В этом случае для простоты я использую QStandardItemModel, поэтому каждая часть элемента, такая как «x» и «y», будет доступна через роли.

В случае QML, так как вы хотите разместить прямоугольники в любомPosition, использование ListView не является правильным вариантом, поскольку этот вид ограничивает позицию, вместо этого вы должны использовать Repeater.

main.py

import os
import sys

from PySide2 import QtCore, QtGui, QtQml

XRole = QtCore.Qt.UserRole + 1000
YRole = QtCore.Qt.UserRole + 1001
AngleRole = QtCore.Qt.UserRole + 1002


class RectangleManager(QtCore.QObject):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.m_model = QtGui.QStandardItemModel(self)

        roles = {XRole: b"x", YRole: b"y", AngleRole: b"angle"}

        self.m_model.setItemRoleNames(roles)

    @QtCore.Property(QtCore.QObject, constant=True)
    def model(self):
        return self.m_model

    @QtCore.Slot(float, float, float)
    def add_rectangle(self, x, y, angle):
        it = QtGui.QStandardItem()
        it.setData(x, XRole)
        it.setData(y, YRole)
        it.setData(angle, AngleRole)
        self.model.appendRow(it)

    @QtCore.Slot()
    def clear_rectangles(self):
        self.model.clear()


def main(args):
    app = QtGui.QGuiApplication(args)

    manager = RectangleManager()

    import random

    for _ in range(10):
        manager.add_rectangle(
            random.randint(0, 500), random.randint(0, 500), random.randint(0, 360)
        )

    engine = QtQml.QQmlApplicationEngine()
    engine.rootContext().setContextProperty("rectangle_manager", manager)
    current_dir = os.path.dirname(os.path.realpath(__file__))
    filename = os.path.join(current_dir, "main.qml")
    engine.load(QtCore.QUrl.fromLocalFile(filename))
    if not engine.rootObjects():
        return -1
    ret = app.exec_()
    return ret


if __name__ == "__main__":
    sys.exit(main(sys.argv))

main.qml

import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow {
    id: root
    width: 640
    height: 480
    visible: true

    Repeater{
        model: rectangle_manager.model

        Rectangle{
            x: model.x
            y: model.y
            rotation: model.angle
            width: 100
            height: 100
            color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
        }
    }
}

enter image description here

...