MenuBar喜欢QML中的行为

时间:2016-08-04 05:04:55

标签: qt qml

我希望在点击矩形时有类似行星的行为。只要单击一个矩形,就会更新模型并显示ListView。每当点击另一个ListView时,我希望此Rectangle消失,并且每次点击都不应附加listmodel。这是我的示例代码。

Card.qml

Rectangle {
    id: card
    width: 50
    height: 100
    color: "pink"
    Item {
        id: rec
        width: 50
        anchors.bottom: parent.top

        ListModel {
            id: menuListModel
        }

        Component {
            id: delegate
            Rectangle {
                width: 50
                height: 20
                color: "blue"
                Text {
                    anchors.fill: parent
                    anchors.centerIn: parent
                    text: commandText
                }
            }
        }

        ListView {
            anchors.fill: parent
            model:menuListModel
            delegate: delegate
            interactive: false
        }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            rec.height += 40;
            menuListModel.append({"commandText" : "Act"});
            menuListModel.append({"commandText" : "Set"});
        }
    }
}

main.qml

Item {
    width: 120
    height: 200
    Row {
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        spacing: 10
        Card {
            id: card1
        }
        Card {
            id: card2
        }
    }
}

此外,我想在点击菜单按钮(即ActSet时调用某些功能。

修改

单击卡片(此处为矩形)时,将使用适当的标志调用以下函数。

property int command_activate:  0x0001
property int command_summon:    0x0002
property int command_spsummon:  0x0004
property int command_mset:      0x0008
property int command_sset:      0x0010
property int command_repos:     0x0020
property int command_attack:    0x0040
property int command_list:      0x0080

function showMenu(flag) {
    if(flag & command_activate) {
        rec.height += 15;
        menuListModel.append({"commandText" : "Activate"});
    }
    if(flag & command_summon) {
        rec.height += 15;
        menuListModel.append({"commandText" : "Normal Summon"});
    }
    if(flag & command_spsummon) {
        rec.height += 15;
        menuListModel.append({"commandText" : "Special Summon"});
    }
    if(flag & command_mset) {
        rec.height += 15;
        menuListModel.append({"commandText" : "Set"});
    }
    if(flag & command_sset) {
        rec.height += 15;
        menuListModel.append({"commandText" : "Set"});
    }
    if(flag & command_repos) {
        if(position & pos_facedown) {
            rec.height += 15;
            menuListModel.append({"commandText" : "Flip Summon"});
        }
        else if(position & pos_attack) {
            rec.height += 15;
            menuListModel.append({"commandText" : "To Defense"});
        }
        else {
            rec.height += 15;
            menuListModel.append({"commandText" : "To Attack"});
        }
    }
    if(flag & command_attack) {
        rec.height += 15;
        menuListModel.append({"commandText" : "Attack"});
    }
    if(flag & command_list) {
        rec.height += 15;
        menuListModel.append({"commandText" : "View"});
    }
}  

因此,简而言之,当点击一张卡片时,必须根据卡片顶部的flag显示一个菜单。

2 个答案:

答案 0 :(得分:1)

您的代码存在一些问题。

您无法命名delegate“代表”。执行此操作时,ListView使用自己的委托属性进行自我设置,从而不会发生任何事情。

另外,为什么不用静态填充ListView,然后使用visible属性切换是否显示?如果您希望在单击其他Card时它消失,则可能必须使用focus属性。

实际上,将焦点设置为true将重置焦点范围内所有其他项目的焦点。这样的事情可能有用:

Rectangle {
    id: card
    ...
    property alias model: list.model

    Component {
        id: mydelegate
        Rectangle {
            width: 50
            height: 20
            ...
        }
    }

    ListView {
        id: list
        visible: card.activeFocus
        anchors.bottom: parent.top
        width: card.width
        delegate: mydelegate
        interactive: false
        height: childrenRect.height
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            card.focus = !card.focus
        }
    }
}

对于调用函数,您可以直接在ListModel中添加要调用的函数的名称。在您的代理中添加MouseArea,并在点击时发送信号。然后,你只需要调用匹配的插槽(同意,this[slot]()语法有点hacky)。

在Card.qml

Rectangle {
    id: card
    ...

    property alias model: list.model
    signal itemClicked(string slot)

    Component {
        id: mydelegate
        Rectangle {
            ...
            MouseArea
            {
                anchors.fill: parent
                onClicked: {
                    if(model.slot)
                        itemClicked(slot)
                }
            }
        }
    }

    ...
}

在main.qml

    ...
    Card
    {
        model: ListModel {
            ListElement{commandText: "Act"; slot: "act"}
            ListElement{commandText: "Set"; slot: "set"}
        }

        function act()
        {
           print("act triggered")
        }

        function set()
        {
           print("set trigggered")
        }

        onItemClicked: { this[slot]() }
    }
    ...

答案 1 :(得分:0)

我无法发表评论,要求澄清,我将根据我的理解陈述我的假设:

当您点击栏中相应的矩形项时,您有一些ListModel,其中包含应弹出的菜单信息。
一旦您单击此栏中的任何其他矩形,弹出的ListView将消失。 (另外:如果单击栏或菜单外的某些内容?或者栏中的项目被选中?)

我只使用一个ListView,并且一旦点击一个按钮就更新/更改模型以及位置(例如边距),因此您不会有多个未使用的对象飞来飞去。 为了不显示任何内容,我认为设置一个空模型就足够了。

您还可以拥有一系列功能。

Row {
    id: row
    property var f: [a, b, c]
    function a() { console.log('a'); }
    function b() { console.log('b'); }
    function c() { console.log('c'); }
    width: 300
    height: 50
    Repeater {
        id: rep
        anchors.fill: parent
        delegate: button
        model: 3
        Rectangle {
            id: button
            width: 98
            height: 50
            border.color: 'black'
            Text {
                text: "a"
                anchors.fill: parent
            }
            MouseArea {
                anchors.fill: parent
                onClicked: row.f[index]()
            }
        }
    }
}

e.g。将调用函数a,b或c - 取决于矩形的索引。

我希望,到目前为止,我可以提供帮助。