上期已经可以实现批量创建基金信息框,并为每个基金信息框的内容做修改,接下来应该开始尝试初步的动态创建QML控件了,但是后来又查了下,QML或者说QT或者说整个UI界有个叫MVC的概念,今天就来说说这个MVC,以及这个MVC对接下来动态增删改基金信息框这个事情有什么帮助.

MVC的英文全称是 Model-View-Controller,看了不少文章,大多喜欢把它解读成这样:数据-布局-样式的感觉,或者说类似于网页端.

数据:是后台提供的,比如说某个PHP写的接口,提供一组数据,比如说每个基金的基金名称,基金代码,净值等信息.

布局:就是我们软件的整个大的界面框架,在网页上应该是HTTP的活,比如说基金信息是一行一行显示的,所以可能本质上每个基金信息框都塞在一个Column里,或者干脆就是 ListView,(这里用 ListView应该更好,符合MVC的感觉).

样式:决定了每行的基金信息框应该怎么显示,是矩形框还是圆角框,每个信息框里显示那些信息.在网页上应该算是CSS的活,当然好像还有点HTTP的部分在里面.

我理解在之前我已经写好的内容里,我们自定义的Fund_info_box组件可以理解为是一个样式(MVC里的 Controller ).接下来,我只需要先搞定布局,用 ListView替代之前的 Column ,就可以直接用 ListView组件自带的model跟delegate属性来搞这事了.

哦对了,顺便一提,我后来又从上一篇内容的代码基础上改了一些东西,更加规范化了一下,在Fund_info_box组件里增加了一些内容并暴露给外部.可以看下代码.

import QtQuick 2.12
import QtQuick.Window 2.12
import Toou2D 1.0
import "."

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("苏阳基金查看器v1.0")
    Column{
        x: 30
        y: 20
        id:layout
        spacing: 10
        Fund_info_box{
            id: fund_info_box_1
            fund_name:"基金1"
        }
        Fund_info_box{
            id: fund_info_box_2
            fund_name:"基金2"
        }
        Fund_info_box{
            id: fund_info_box_3
            fund_name:"基金3"
        }
        Fund_info_box{
            id: fund_info_box_4
            fund_name:"基金4"
        }
        Fund_info_box{
            id: fund_info_box_5
            fund_name:"基金5"
        }
    }
}
import QtQuick 2.12
import Toou2D 1.0


TRectangle{
    id: tRectangle
    width: 600
    height: 60
    color: "#409EFF"
    radius: 2
    theme.enabled: false
    property alias fund_name : fund_name_tlabel.text                    // 对外暴露基金名称属性
    property alias fund_expect_worth : fund_expect_worth_tlabel.text    // 对外暴露基金净值估算属性
    property alias fund_expect_growth : fund_expect_growth_tlabel.text  // 对外暴露基金净单位净值估算日涨幅属性
    property alias fund_info_box_background_color : tRectangle.color    // 对外暴露基金信息框的背景颜色属性
    signal remove_fund_info_box()           // 定义点击删除按钮的信号

    TLabel{
        id: fund_name_tlabel                // 基金名标签
        x:10
        y:10
        width: 150
        height: 40
        color: "#FFF"
        text: "基金名"
        theme.enabled: false
    }
    TLabel{
        id: fund_expect_worth_tlabel        // 基金净值估算标签
        x:250
        y:10
        width: 150
        height: 40
        color: "#FFF"
        text: "净值估算:NULL"
        theme.enabled: false
    }
    TLabel{
        id: fund_expect_growth_tlabel        // 基金净单位净值估算日涨幅标签
        x:10
        y:35
        width: 150
        height: 40
        color: "#FFF"
        text: "净值估算日涨幅:NULL%"
        theme.enabled: false
    }
    TIconButton{
        anchors.verticalCenter: parent.verticalCenter
        anchors.right: parent.right
        anchors.rightMargin: 10
        label.text: "删除"
        label.font.bold: true
        label.color: "#FFF"
        background.color: "#609EFF"
        icon.source: TAwesomeType.FA_close
        icon.color:label.color
        theme.enabled: false
        onClicked:
        {
            // 发射信号
            tRectangle.remove_fund_info_box()
        }
    }
}

上面代码的效果就是下面这张图的效果.是不是感觉帅了很多?

接下来开始这一期的修改,为了更加符合MVC的概念.我在main.qml里做了如下修改:

import QtQuick 2.12
import QtQuick.Window 2.12
import Toou2D 1.0
import "."

Window {
    id: window
    visible: true
    width: 640
    height: 480
    title: qsTr("苏阳基金查看器v1.0")


    ListView{
        anchors.right: parent.right
        anchors.rightMargin: 10
        anchors.left: parent.left
        anchors.leftMargin: 10
        anchors.top: parent.top
        anchors.topMargin: 10
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 30

        width: 600
        height: 400
        id:listView
        spacing: 10
        model:model1
        delegate:delegate1
    }


    ListModel{
        id: model1
        ListElement{name: "A"}
        ListElement{name: "B"}
        ListElement{name: "C"}
        ListElement{name: "D"}
    }

    Component {
           id: delegate1
           Fund_info_box
           {
               fund_name:name
               anchors.right: parent.right
               anchors.left: parent.left
           }
    }
}

将原先的Column布局组件改成了ListView,并新建了一个Component组件,id为delegate1,里面包含了我的Fund_info_box组件,并对我的Fund_info_box的基金名称用一个name来赋值(这个name哪来的后面会说).然后设置了一些布局上的东西,左右各自贴着父组件的左右壁(这个跟本文主题无所谓,就是布局上的修改).

然后创建了一个ListModel,id为model1,并在里面建了4个ListElement,每个ListElement里都有一个name属性,并赋值成我想要基金信息框显示的基金名称.

然后将ListView的model属性用model1赋值,然后把 ListView的delegate属性用delegate1赋值.大功告成,效果是下面这样的.

这样就很明确了,以 ListView作为大的布局框架,然后以Component组件,其实就是 Fund_info_box来做为样式,负责显示的具体样子.然后以ListModel作为数据用 ListModel里的4个ListElement作为实际的4个数据在ListView的布局框架里生成4个Component( Fund_info_box)组件.


一个电子工程师的自我修养