0

假设我们有一个列表模型:

from PySide2.QtCore import Qt, QAbstractListModel, QModelIndex
import numpy as np

class AxisModel(QAbstractListModel):
    MaxRole = Qt.UserRole + 1015
    MinRole = Qt.UserRole + 1016
    TicksRole = Qt.UserRole + 1017

    def __init__(self, min_, max_, price_unit, parent=None):
        super(AxisModel, self).__init__(parent)
        self.max = float(max_)
        self.min = float(min_)
        self.price_unit = float(price_unit)
        self.ticks = np.arange(self.min, self.max + self.price_unit, self.price_unit).tolist()

    def rowCount(self, parent=QModelIndex()):
        if parent.isValid():
            return 0
        return len(self.ticks)

    def data(self, index: QModelIndex, role):
        if 0 > index.row() > self.rowCount() and not index.isValid():
            return None
        if role == AxisModel.MinRole:
            return self.min
        if role == AxisModel.MaxRole:
            return self.max
        if role == AxisModel.TicksRole:
            return self.ticks[index.row()]

    def roleNames(self):
        roles = dict()
        roles[AxisModel.MinRole] = b"min"
        roles[AxisModel.MaxRole] = b"max"
        roles[AxisModel.TicksRole] = b"ticks"
        return roles

这稍后在 python 代码中使用:

(...)
    axismodel = AxisModel(min_=min_, max_=max_, price_unit=0.25)

    app = QGuiApplication(sys.argv)
    view = QQuickView()
    view.setResizeMode(QQuickView.SizeRootObjectToView)
    # register models
    view.rootContext().setContextProperty("axis_model", axismodel)
    view.rootContext().setContextProperty("ts_model", tsmodel) # some other model

    qml_file = os.path.join("/home/user/code/project", "simple_test.qml")
    view.setSource(QUrl.fromLocalFile(os.path.abspath(qml_file)))
    if view.status() == QQuickView.Error:
        sys.exit(-1)
    view.show()

    app.exec_()

使用它的 QML 文件(简化):

Item {
    Axis {
        model: axis_model
    }
}

轴项:

Item {
    id: axis
    property ListModel model
    property real max: model.max
    property real min: model.min
(...)
}

这会产生一个错误: Unable to assign AxisModel to QQmlListModel

好的,AxisModel 在技术上不是 QQmlListModel,但它们都继承自 QAbstractItemModel。我不知道如何解决这个问题。我的两个想法是:

  1. ListModel使用与Axis.qml 定义中不同的类型。我不知道是哪一个。我尝试了 QObject、QVariant,结果不是 QML 类型。Item 不起作用,因为 AxisModel 不是 QQuickItem 实例
  2. 在 python 代码中使用一些 PySide2 注释来注释 AxisModel 类,这将通知 QML 引擎有关类型。我不知道如何解决这个问题。

谢谢你的时间。

4

2 回答 2

1

我认为您已经正确地确定了问题所在。Axis模型不是QQmlListModel,所以不能赋值。

但是您应该能够像这样简单地定义您的模型:

property var model
于 2020-09-07T15:33:44.677 回答
0

要添加到已接受的答案,以下是使其正常工作所需的更改。

轴项 -var用于让 QML 自行决定类型:

Item {
    id: axis
    property var model
    property var min
    property var max
(...)
}

QML中轴项的调用:

Item {

    AxisTest {
        model: axis_model
        min: axis_model.min
        max: axis_model.max
    }
(...)
}

然后,在python中:

  1. 删除最小/最大角色

  2. 为每个属性定义 getter、setter 和更改信号(我仍然不知道信号应该做什么,所以现在是通过)

  3. 在类(不是实例)上注册一个属性,其中绑定了 getter、setter 和通知信号

  4. 在构造函数中设置每个属性的初始值

class AxisModel(QAbstractListModel):
    def get_min(self):
        return self._min

    def set_min(self, _min):
        self._min = _min

    def get_max(self):
        return self._max

    def set_max(self, _max):
        self._max = _max

    @Signal
    def max_changed(self, _max):
        pass

    @Signal
    def min_changed(self, _min):
        pass

    TicksRole = Qt.UserRole + 1015
    max = Property(float, get_max, set_max, notify=max_changed)
    min = Property(float, get_min, set_min, notify=min_changed)

    def __init__(self, min_, max_, price_unit, parent=None):
        super(AxisModel, self).__init__(parent)
        self._max = float(max_)
        self._min = float(min_)
        self.ticks = np.arange(float(min_), float(max_) + float(price_unit), float(price_unit)).tolist()

    def rowCount(self, parent=QModelIndex()):
        if parent.isValid():
            return 0
        return len(self.ticks)

    def data(self, index: QModelIndex, role):
        if 0 > index.row() > self.rowCount() and not index.isValid():
            return None
        if role == AxisModel.TicksRole:
            return self.ticks[index.row()]
        else:
            return None

    def roleNames(self):
        roles = dict()
        roles[AxisModel.TicksRole] = b"ticks"
        return roles

于 2020-09-07T20:36:51.913 回答