model.rowCount()不会绑定到Item的属性

时间:2018-08-07 13:41:21

标签: qt qml scrollview qtquickcontrols2

我有一个ListView,它是用Qml中一个名为rootModel的自定义C ++模型初始化的。 该模型继承了QAbstractListModel并将一个QVector<customType>定义为私有成员以填充模型。

在我的ApplicationWindow中,我创建了一个Dialog,在其中更改模型并调用setList()函数以对其进行更新。效果很好。

我还想将模型的大小连接到ScrollView的{​​{1}}属性。此属性将定义int中的children

问题是,当我尝试将此属性绑定到模型的大小时,应用程序崩溃。

仅供参考,该模型的所有修改均遵循Qt的规则。 RowLayoutrowCount()。我也尝试过使用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)

2 个答案:

答案 0 :(得分:2)

只有q属性允许绑定,在您的情况下Q_INVOKABLE是不允许的,因此您必须创建它,为此,我们将信号rowsInsertedrowsRemoved用作如下所示:

*。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