Qt之MVC编程

零、前言

MVC在Qt中叫做MVD,Model+View+Delegate。关于Model,Qt提供了以QAbstractItemModel为父类的相关类。如图:

 

①、QAbstractItemModel提供给数据一个接口,它非常灵活,基本满足views的需要,无论数据用什么样的形式表现,如tables,lists,trees;
②、如果model基于list、table形式的数据结构,可从QAbstractListModel、QAbstractTableModel开始做起,因为它们提供了适当的常规功能的缺省实现;
③、QStringListModel 用于存储简单的QString列表;
④、QStandardItemModel 管理复杂的树型结构数据项,每项都可以包含任意数据;
⑤、QDirModel 提供本地文件系统中的文件与目录信息;
⑥、QSqlQueryModel、QSqlTableModel、QSqlRelationTableModel用来访问数据库;
假如这些标准Model不满足需要,可子类化QAbstractItemModel、QAbstractListModel、QAbstractTableModel等来定制。

 

PS:

根据这个原理,QXXXView和QXXXWidget的区别:View可以手动设置自定义Model进去,Widget只能用标准的自带Model;

在QML中Grid和GridView区别也是,带View的是可以设置Model的。

 

一、静态视图

1、Repeater+model:数字

import QtQuick 2.0
Column{
    spacing:2
    Repeater{
        model:10
        Rectangle{
            width:100
            height:20
            radius:3
            color:"lightBlue"
            Text{
                anchors.centerIn: parent
                text:index
            }
        }
    }
}

Repeater会传递分配给delegate的index;

这里Rectangle前省略了delegate,建议都加上,免得看不懂。

 

 2、Repeater+model:js序列

序列可以是字符串、整数或者对象,以字符串为例

import QtQuick 2.0
Column {
    spacing: 2
    Repeater {
        model: ["Enterprise", "Colombia", "Challenger", "Discovery", "Endeav"]
        delegate:  Rectangle {
            width: 100
            height: 20
            radius: 3
            color: "lightBlue"
            Text {
                anchors.centerIn: parent
                text: index +": "+modelData
            }
        }
    }
}

 Repeater会传递分配给delegate的index和序列对象,这里是字符串。

 

  3、Repeater+model:ListModel

import QtQuick 2.0
import QtQml.Models 2.15
Column{
    spacing:2
    Repeater{
        model:ListModel{
            ListElement{name:"Mercury";surfaceColor:"gray"}
            ListElement{name:"Venus";surfaceColor:"yellow"}
            ListElement{name:"Earth";surfaceColor:"blue"}
            ListElement{name:"Mars";surfaceColor:"orange"}
            ListElement{name:"Jupiter";surfaceColor:"orange"}
            ListElement{name:"Saturn";surfaceColor:"yellow"}
            ListElement{name:"Uranus";surfaceColor:"lightBlue"}
            ListElement{name:"Neptune";surfaceColor:"lightBlue"}
        }
        delegate:Rectangle{
            width:100
            height:20
            radius:3
            color:"lightBlue"
            Text{
                anchors.centerIn:parent
                text:name
            }
            Rectangle{
                anchors.left:parent.left
                anchors.verticalCenter:parent.verticalCenter
                anchors.leftMargin:2
                width:16
                height:16
                radius:8
                border.color:"black"
                border.width:1
                color:surfaceColor
            }
        }
    }
}

 

 

  Repeater会传递分配给delegate的index和ListElement对象,可访问ListElement里的所有元素,这是里name、serfaceColor。

 

PS:

①、Repeator的model里可以放的数据如下,

 

 

 一个数字代表着生成多少个模型;

一个ListModel或QAbstractItemModel子类;

一个字符串列表;

一个对象列表。

 

4、ListView+ListModel

import QtQuick 2.5

Item {
    id: root

    width: 400
    height: 300

    ListView {
        anchors.fill: parent
        model: fruitModel
        delegate: Row {
            Text { text: "Fruit: " + name }
            Text { text: "Cost: $" + cost }
        }
    }
    ListModel {
        id: fruitModel

        ListElement {
            name: "Apple"
            cost: 2.45
        }
        ListElement {
            name: "Orange"
            cost: 3.25
        }
        ListElement {
            name: "Banana"
            cost: 1.95
        }
    }
}

 

 

 二、动态视图

1、动态为GridView增删对象

import QtQuick 2.0
import QtQml.Models 2.15
Rectangle {
    width: 480;
    height: 300;

    //背景色渐变
    gradient: Gradient {
        GradientStop { position: 0.0; color: "#dbddde"; }
        GradientStop { position: 1.0; color: "#5fc9f8"; }
    }

    //list模型默认9项
    ListModel {
        id: theModel
        ListElement { number: 0; }
        ListElement { number: 1; }
        ListElement { number: 2; }
        ListElement { number: 3; }
        ListElement { number: 4; }
        ListElement { number: 5; }
        ListElement { number: 6; }
        ListElement { number: 7; }
        ListElement { number: 8; }
        ListElement { number: 9; }
    }

    //Add Item按钮
    Rectangle {
        anchors.left: parent.left;
        anchors.right: parent.right;
        anchors.bottom: parent.bottom;
        anchors.margins: 20;
        height: 40;
        color: "#53d769";
        border.color: Qt.lighter(color, 1.1);
        Text {
            anchors.centerIn: parent;
            text: "Add item!";
        }
        //点击时新增项  实现model的动态新增
        MouseArea {
            anchors.fill: parent;
            onClicked: {
                theModel.append({"number": ++parent.count});
            }
        }
        property int count: 9;//
    }
    GridView {
        anchors.fill: parent;
        anchors.margins: 20;
        anchors.bottomMargin: 80;
        clip: true;
        model: theModel;//绑定数据源
        cellWidth: 45;//设置项大小
        cellHeight: 45;
        delegate: numberDelegate;//设置绘制代理
    }

    //自定义绘制代理
    Component {
        id: numberDelegate;
        Rectangle {
            id: wrapper;
            width: 40;
            height: 40;
            //首先是一个渐变的矩形框
            gradient: Gradient {
                GradientStop { position: 0.0; color: "#f8306a"; }
                GradientStop { position: 1.0; color: "#fb5b40"; }
            }
            //文本值是number的数值
            Text {
                anchors.centerIn: parent;
                font.pixelSize: 10;
                text: number;
          //text: index;//显示当前序号 }
//鼠标点击代理时,移除点击项 MouseArea { anchors.fill: parent; onClicked: { if (!wrapper.GridView.delayRemove)//是否延迟移除 { theModel.remove(index); } } } //GridView移除项 顺序动画 GridView.onRemove: SequentialAnimation { //属性变化 PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: true; } //数字动画 NumberAnimation { target: wrapper;//目标对象 property: "scale";//执行动画的属性 to: 0;//结束值 duration: 250;//动画持续时长 easing.type: Easing.InOutQuad;//动画执行曲线 } PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false; } } //GridView新增项 顺序动画 GridView.onAdd: SequentialAnimation { NumberAnimation { target: wrapper; property: "scale"; from: 0;//开始值 to: 1; duration: 250; easing.type: Easing.InOutQuad; } } } } }

 

 

 

 

 

 

 

https://zhuanlan.zhihu.com/p/66928607

posted @ 2021-11-30 10:09  朱小勇  阅读(1415)  评论(0编辑  收藏  举报