【问题标题】:MenuBar like behaviour in QMLQML 中的类似菜单栏的行为
【发布时间】:2016-08-04 05:04:54
【问题描述】:

我希望在单击矩形时具有类似菜单栏的行为。每当单击矩形时,模型就会更新并显示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"});
        }
    }
}

ma​​in.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 显示菜单。

【问题讨论】:

    标签: qt qml


    【解决方案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]() }
        }
        ...
    

    【讨论】:

    • delegate 用作id 对我来说是一个糟糕的判断。我无法静态填写我的ListView,因为有很多按钮,如ActSetSummon 等,每个按钮的可见性都由一个函数决定。所以它是一个动态模型。
    • 您能否提供有关如何确定可见性的更多信息?也许用代码示例编辑你的答案
    【解决方案2】:

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

    您有多个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]()
                }
            }
        }
    }
    

    例如将调用函数 a、b 或 c - 取决于矩形的索引。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-21
      相关资源
      最近更新 更多