首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在qml委托可视化模型更改上更新c++模型

在qml委托可视化模型更改上更新c++模型
EN

Stack Overflow用户
提问于 2022-11-28 23:17:11
回答 2查看 57关注 0票数 0

在c++中定义了一个简单的c++,通过自定义DelegateDelegateModelQML ListView中显示。ListView可以通过拖放重新排序:

代码语言:javascript
运行
复制
// The DropArea is part of the delegate `comp_container`
DropArea{
    anchors{fill: parent}
    keys: ["pageitem"]
    onEntered: {
        let from = drag.source.DelegateModel.itemsIndex
        let to = dragAreaPage.DelegateModel.itemsIndex
        if ( pageItemDragOperationStartIndex === -1 ){
            pageItemDragOperationStartIndex = from
        }
        pageItemDragOperationFinalIndex = to
        console.log(from + "->" + to)
        visualModel.items.move(from,to)
    }
}

这里是委托模型,pageproxymodel是c++模型。

代码语言:javascript
运行
复制
DelegateModel {
    id: visualModel
    model: pageproxymodel
    delegate: comp_container
}

如何更新c++模型?委托的顶级项是一个MouseArea,我处理发布处理程序中的重新排序:

代码语言:javascript
运行
复制
onReleased: {
    if ( pageItemDragOperationStartIndex !== -1 && pageItemDragOperationFinalIndex !== -1 ){
        console.log("Page item final drag operation: " + pageItemDragOperationStartIndex + "->" + pageItemDragOperationFinalIndex)
        pageproxymodel.move(pageItemDragOperationStartIndex, pageItemDragOperationFinalIndex)
        pageItemDragOperationStartIndex = -1
        pageItemDragOperationFinalIndex = -1
    }
}

c++模型的move函数将调用转发给该处理程序:

代码语言:javascript
运行
复制
bool PageModel::moveRow(const QModelIndex &sourceParent,
                        int sourceRow,
                        const QModelIndex &destinationParent,
                        int destinationChild)
{
    if ( sourceRow < 0 || sourceRow > rowCount()-1 ||
         destinationChild < 0 || destinationChild > rowCount() )
    {
        return false;
    }

    beginMoveRows(sourceParent, sourceRow, sourceRow, destinationParent, destinationChild);
 
    QList<QStandardItem*> rowItems = takeRow(sourceRow);
    insertRow(destinationChild, rowItems);

    endMoveRows();

    return true;
}

使用上面的c++模型代码,它在QML中的发布处理程序上崩溃:

我尝试过其他的方法来观察它的效果,没有撞车,但也没有预期的行为。

  • 删除一行(删除2 (!)( QML ListView中的行)
  • 删除一行而不调用begin/end (删除QML ListView中的1行,但不能正确)
  • 删除并插入一行,不需要开始/结束调用(QML ListView看起来很好,但几次移动后就不同步了)

基本上,我想要做的就是通过ListView模型保存c++状态,毕竟这是一个标准用例,简单的东西在我这一边一定是错误的,但是我看不见它。

EN

回答 2

Stack Overflow用户

发布于 2022-11-30 02:43:15

我喜欢用DelegateModel做的一件事就是使用DelegateModelGroup。通过声明一个名为"all“的组,它引入了一个附加属性allIndex,该属性对于重新排序后跟踪项目非常有用。下面的示例使用DelegateModelMouseArea实现了一个DropArea。在拖动模式下,我禁用了所有的MouseArea,这样DropArea就有机会做出响应。

代码语言:javascript
运行
复制
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

Page {
    property int activeMouseArea: -1
    ListView {
        id: listView
        width: 420
        height: parent.height
        model: SampleDelegateModel { }
        ScrollBar.vertical: ScrollBar {
            width: 20
            policy: ScrollBar.AlwaysOn
        }
    }
    footer: Text { id: dbg }
}

// SampleData.qml
import QtQuick
import QtQuick.Controls

ListModel {
    ListElement { name: "Steve Jobs" }
    ListElement { name: "Jeff Bezos" }
    ListElement { name: "Bill Gates" }
    ListElement { name: "Elon Musk" }
}

// SampleDelegateModel.qml
import QtQuick
import QtQuick.Controls
import QtQml.Models

DelegateModel {
    id: delegateModel
    model: SampleData { }
    delegate: SampleDelegate { }
    groups: [
        DelegateModelGroup {
            id: allItems
            name: "all"
            includeByDefault: true
        }
    ]
    filterOnGroup: "all"
    function moveItem(from, to) {
        dbg.text = `Debugging: moveItem(${from},${to})`;
        allItems.move(from, to);
    }
}

// SampleDelegate.qml
import QtQuick
import QtQuick.Controls
import QtQml.Models

Rectangle {
    property int allIndex: DelegateModel.allIndex
    width: 400
    height: labelText.height + 20
    border.color: "grey"
    z: mouseArea.drag.active || mouseArea.pressed ? 2 : 1
    property int dragTo: -1
    Drag.active: mouseArea.drag.active

    Text {
        id: labelText
        anchors.centerIn: parent
        text: allIndex + ": [" + index + "] " + name
    }

    DropArea {
        anchors.fill: parent
        onEntered: drag.source.dragTo = allIndex
    }

    MouseArea {
        id: mouseArea
        anchors.fill: parent
        drag.target: parent
        property point startPoint
        enabled: activeMouseArea === -1
        onPressed: {
            activeMouseArea = allIndex;
            dragTo = -1;
            startPoint = Qt.point(parent.x, parent.y);
        }
        onReleased: {
            activeMouseArea = -1;
            [parent.x,parent.y] = [startPoint.x, startPoint.y];
            Qt.callLater(delegateModel.moveItem, allIndex, dragTo);
        }
    }
}

你可以在网上试试!

票数 1
EN

Stack Overflow用户

发布于 2022-11-29 18:34:29

发现错误:pageItemDragOperationStartIndexpageItemDragOperationFinalIndex变量,每个委托的一部分,但不是页面的一部分。另外,正如注释中指出的那样,使用QStandardItemModel不需要调用begin/end函数。现在它就像一种魅力。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74607500

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档