我有一个ListView
,它是用Qml中一个名为rootModel
的自定义C ++模型初始化的。
该模型继承了QAbstractListModel
并将一个QVector<customType>
定义为私有成员以填充模型。
在我的ApplicationWindow
中,我创建了一个Dialog
,在其中更改模型并调用setList()
函数以对其进行更新。效果很好。
我还想将模型的大小连接到ScrollView
的{{1}}属性。此属性将定义int
中的children
。
问题是,当我尝试将此属性绑定到模型的大小时,应用程序崩溃。
仅供参考,该模型的所有修改均遵循Qt的规则。 RowLayout
是rowCount()
。我也尝试过使用Q_INVOKABLE
处理程序,但这没有用(我在文档中检查到onModelChanged
发出时会发出此信号,这是在modelReset()
内部通过setList()
我相信这是一个简单的过程(在我的项目中已经执行了很多次属性绑定),但是不能按预期工作。
我引用了我的项目的一些示例代码。
endResetModel()
[编辑1]
仔细研究后,我意识到,即使使用当前的实现方式正确绑定到模型的大小,我仍然无法按需创建所需数量的//main.qml
ConfiguredChannels{
id: configuredList
anchors{
left: parent.left
top: devices.bottom
right: tabs.left
bottom: parent.bottom
}
}
TabArea {
id: tabs
y: toolBar.height
x: parent.width / 8
anchors {
top: toolBar.bottom
}
width: 3 * parent.width / 4
height: 3 * parent.height / 4
countPWM: configuredList.model.rowCount() //This is where I want to bind.
}
//ConfiguredChannels.qml
id: confChanView
header: confChanHeader
model: ChannelModel{
id: rootModel
list: channelList
}
//TabArea.qml
Item{
id: tabAreaRoot
property alias channelsPWM: channelsPWM
property int countPWM
ScrollView{
id: scrollPWM
anchors.fill: parent
contentItem: channelsPWM.children
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOn
RowLayout{
id: channelsPWM
spacing: 0
Layout.fillHeight: true
Layout.fillWidth: true
Component.onCompleted: {
var namesPWM = [];
for (var i=0; i<countPWM; i++){
namesPWM.push("Channel"+(i+1));
}
createChannels(countPWM, "PWM", channelsPWM, namesPWM);
}
}
}
的{{1}}(在我更改之后RowLayout
children
中的模型)。
那是因为我将它们的创建放入了Dialog
的{{1}}处理程序中。一旦Configuration.qml
首次在RowLayout
内部初始化,该处理程序的内容就会执行。之后,Component.onCompleted
的任何其他更改都不会有所不同,因为该组件已经完成!如果此时我错了,请纠正我。
基于此,我遵循了另一个实现。我创建了名为Configuration.qml
的{{1}}的“包装器”函数。这样,为了正确更新main.qml
的{{1}},我必须调用此函数。
countPWM
[编辑2]
尽管EDIT 1中的解决方案有效并且为我的createChannels
产生了正确的createStrips(countPWM)
,但我认为这还不够好,我相信最好的实现方法是将模型的尺寸更改与对RowLayout
函数。像这样:
children
甚至更好的做法是,将\\Configuration.qml
\\more code
currentModel.setList(newList)
tabs.createStrips(tableModel.count) \\tableModel is used to populate the newList that will be set to the model
newList.clear()
\\more code
\\TabArea.qml
function createStrips(countPWM){
var namesPWM = [];
for (var i=0; i<countPWM; i++){
namesPWM.push("Channel"+(i+1));
}
createChannels(countPWM, "PWM", channelsPWM, namesPWM);
}
function createChannels(counter, channelType, channelParent, channelMapping){
if ( channelParent.children.length !== 0){
console.log("destroying");
for ( var j = channelParent.children.length; j > 0 ; j--){
channelParent.children[j-1].destroy();
}
}
for (var i=0;i<counter;i++){
var component = Qt.createComponent(channelType+".qml");
if( component.status !== Component.Ready )
{
if( component.status === Component.Error )
console.debug("Error:"+ component.errorString() );
return; // or maybe throw
}
var channels =component.createObject(channelParent, { "id": channelType+(i+1), "channelText.text": channelMapping[i]});
}
创建为自定义children
信号处理程序,该信号处理程序将在每次更改模型大小时发出。 (我如上所述尝试了ScrollView
,但是没有用。在这种情况下可能会丢失该信号)
[解决方案]
我按照接受的答案以及此link的说明进行操作。
我在名为createStrips(countPWM)
的头文件中用\\main.qml
ConfiguredChannels{
id: configuredList
anchors{
left: parent.left
top: devices.bottom
right: tabs.left
bottom: parent.bottom
}
onModelChanged: tabs.createStrips(model.rowCount) //or an appropriate signal handler defined on C++ side
}
children
和信号qml
在模型定义中添加了onModelChanged
。另外,在用于更新模型的函数Q_PROPERTY
中,我在实现的末尾添加了rowCount
。最后,我将此信号与QML中的函数NOTIFY
连接起来。现在,每次更改模型大小时,我的rowCountChanged
都会自动更新显示为void rowCountChanged();
的子项的条。
setList(newList)
答案 0 :(得分:2)
只有q属性允许绑定,在您的情况下Q_INVOKABLE
是不允许的,因此您必须创建它,为此,我们将信号rowsInserted
和rowsRemoved
用作如下所示:
*。h
Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
public:
...
signals:
void rowCountChanged();
*。cpp
//constructor
connect(this, &QAbstractListModel::rowsInserted, this, &YourModel::rowCountChanged);
connect(this, &QAbstractListModel::rowsRemoved, this, &YourModel::rowCountChanged);
*。qml
countPWM: configuredList.model.rowCount // without ()
注意:
我假设在添加或删除元素时,您正在使用:
beginInsertRows(QModelIndex(), rowCount(), rowCount());
//append data
endInsertRows();
或者:
beginRemoveRows(QModelIndex(), from, to)
// remove
endRemoveRows();
答案 1 :(得分:0)
您无法绑定到Q_INVOKABLE
,因为与更改信号没有关联。
创建一个Q_PROPERTY(count READ rowCount NOTIFY rowCountChanged)
或类似的东西。确保在插入或删除行时发出信号rowCountChanged
。
当然,如果您有一个
Q_PROPERTY(count READ count NOTIFY countChanged)
int count() { return rowCount(); }
并确保发出countChanged
。
然后,您可以绑定到属性count
。