代码之家  ›  专栏  ›  技术社区  ›  K.Tsakalis

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

  •  1
  • K.Tsakalis  · 技术社区  · 6 年前

    我有一个 ListView 用自定义C++模型初始化 rootModel 在Qml内。 模型继承 QAbstractListModel 定义了 QVector<customType> 作为私有成员填充模型。

    在我的 ApplicationWindow 我创造了一个 Dialog 其中我更改了模型并调用 setList() 函数来更新它。这很管用。

    我还想将模型的大小连接到 ScrollView int 财产。此属性将定义 children 一个 RowLayout .

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

    仅供参考,模型的所有修改都遵循Qt的规则。 rowCount() Q_INVOKABLE . 我也试过用 onModelChanged 处理程序,但这不起作用(我在文档中检查过,当 modelReset() 是在里面发射的 设置列表() 通过 endResetModel()

    我相信这是一个简单的过程(在我的项目中已经多次执行了属性绑定),但并没有如预期的那样工作。

    我引用了我的项目的一些示例代码。

    //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] 在仔细观察之后,我意识到使用当前的实现,即使我正确地绑定到模型的大小,我仍然无法创建所需数量的 行列式 儿童 按需(在 对话 Configuration.qml ).

    那是因为我把他们的创造放在里面 行列式 Component.onCompleted 处理程序。此处理程序的内容将在 配置.qml 将在内部初始化 main.qml 这是第一次。在那之后 countPWM 不会有什么不同,因为组件已经完成!拜托 纠正我 如果我在这一点上错了。

    基于此,我遵循了另一个实现。我已经创建了一个“wrapper”函数 createChannels ,命名为 createStrips(countPWM) 。这样,才能正确更新 行列式 儿童 我必须调用这个函数。

    \\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]});
        }
    

    [编辑2] 尽管EDIT 1中的解决方案可以工作并产生 儿童 为了我的 卷轴视图 我认为它不够好,我认为最好的实现是将模型的大小更改与调用绑定到 创建条带(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
    }
    

    或许更好的是 儿童 作为一种习俗 qml 每次更改模型大小时将发出的信号处理程序。(我试过 模型更改时 如上所述,但不起作用。可能我不见了,在这种情况下发出的是这个信号)

    [解决方案]

    我遵循了接受答案的指示 link .

    我加了一个 Q_PROPERTY 在名为 rowCount NOTIFY rowCountChanged 以及信号 void rowCountChanged(); . 而且,在函数内部 setList(newList) 我用它来更新模型,我在实现的末尾添加了 emit rowCountChanged(); . 最后我把这个信号和我的功能连接起来 createStrips(count) 在QML内。现在每次模型尺寸改变,我的 卷轴视图 将自动更新显示为 行列式 的孩子们。

    \\ChannelModel.h
    ...
    Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
    ...
    signals:
    void rowCountChanged();
    
    \\ChannelModel.cpp
    void ChannelModel::setList(ChannelList *list)
    {
    beginResetModel();
    ...
    endRestModel();
    emit rowCountChanged();
    }
    
    \\main.qml
    Connections {
        target: configuredList.model
        onRowCountChanged: tabs.createStrips(configuredList.model.rowCount)
    }
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   eyllanesc Yonghwan Shin    6 年前

    只有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();
    
        2
  •  0
  •   derM - not here for BOT dreams    6 年前

    你不能和一个 Q_INVOKABLE 因为与变化信号没有关联。

    创建 Q_PROPERTY(count READ rowCount NOTIFY rowCountChanged) 或者类似的事情。确保信号 rowCountChanged 在插入或移除行时发出。

    当然,如果你有一个

     Q_PROPERTY(count READ count NOTIFY countChanged)
    
     int count() { return rowCount(); }
    

    确保发出 countChanged .

    然后可以绑定到属性 count .