问题描述
假设我们有一个列表模型:
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。我不知道该如何解决。我的两个想法是:
- 在Axis.qml定义中使用与
ListModel
不同的类型。我不知道是哪一个。我尝试了QObject,QVariant,结果发现它不是QML类型。 Item不起作用,因为AxisModel不是QQuickItem实例 - 使用一些pyside2注释在python代码中注释AxisModel类,该注释将通知QML引擎有关类型。我不知道该如何处理。
感谢您的时间。
解决方法
我认为您已经正确识别了问题。轴模型不是QQmlListModel,因此无法分配。
但是您应该能够像这样简单地定义模型:
property var model
,
要添加到已接受的答案中,请进行以下更改以使其正常工作。
轴项-使用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中:
-
删除最小/最大角色
-
为每个属性定义吸气剂,设置器和更改信号(我仍然不知道信号应该做什么,所以现在是通行证)
-
在类(不是实例)上注册一个属性,该属性绑定了getter,setter和通知信号
-
设置构造函数中每个属性的初始值
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