【Qt开发】qml组件下拉列表的实现(一)

时间:2022-08-10 10:17:20

由于ComboBox需要定制,于是根据已有的的例子,自己重写了一下该控件的交互和样式。主要修改的地方有两点:(1)当鼠标离开下拉区域时,下拉列表将自动收回。不过可能实现的效果不是很好,当鼠标滑动速度较快时列表收回的动作并没有被触发。(2)调整了高亮效果。当鼠标划过和被选中时的状态有所区分,主要响应了三个槽函数: onClick(),onEnter(),onExited()。

在修改上述的第一点时,遇到了一点问题: 父组件和子组件的MouseArea,只能有其中一个会响应鼠标的事件。也就是当Mouse事件被其中一个组件捕获了,那么该事件就不会再传递下去,其他组件就捕捉不到这个事件了。所以当子组件MouseArea有效时(用作高亮效果的展示 ),父组件MouseArea被屏蔽了(检测不到鼠标是否离开了下拉区域)。没有想到好的解决方法,就用了一种有点取巧但又很简单的方法: 子组件被包含在父组件中,并且父组件的尺寸比子组件大一些;当鼠标坐标移出子组件时,父控件MouseArea就有效了。

废话不多说了,直接上代码(qml):


// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
 
Rectangle {
    id:comboBox
    property variant items: ["test0", "test1", "test2", "test3"]
    property alias selectedItem: chosenItemText.text;
    property alias selectedIndex: listView.currentIndex;
    signal comboClicked;
    width: 110;
    height: 30;
    smooth:true;
 
    Rectangle {
        id:chosenItem
        radius:4;
        width:parent.width;
        height:comboBox.height;
        color: "#2EB3FF"
        smooth:true;
        Text {
            anchors.top: parent.top;
            anchors.left: parent.left;
            anchors.margins: 3;
            anchors.verticalCenter: parent.verticalCenter
            id:chosenItemText
            text:comboBox.items[0];
            font.family: "Arial"
            font.pointSize: 14;
            smooth:true
        }
 
        MouseArea {
            anchors.fill: parent;
            onClicked: {
                comboBox.state = comboBox.state==="dropDown"?"":"dropDown"
            }
        }
    }
 
    Rectangle {
        id:dropDown
        width:comboBox.width;
        height:0
        clip:true;
        radius:4;
        anchors.top: chosenItem.bottom;
        anchors.topMargin: 2
        color: "lightgray"
 
        Rectangle{
            id: dropDownMask
            height: 3
            width:parent.width
            anchors.bottom: listView.top
        }
 
        ListView {
            id:listView
            height:250
            width: dropDown.width-4
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.top: dropDownMask.bottom
            anchors.topMargin: -1
            z:1
 
            model: comboBox.items
            currentIndex: 0
            delegate: Item{
                width:listView.width;
                height: comboBox.height;
 
                Rectangle {
                    id: mouseMoveHighLight
                    width:listView.width;
                    height:comboBox.height;
                    color: "green";
                    opacity: 0
                    radius: 4
                    z:0
                }
 
                Text {
                    text: modelData
                    anchors.top: parent.top;
                    anchors.left: parent.left;
                    anchors.margins: 5;
                    font.pointSize: 14;
                    z:1
                }
                MouseArea {
                    anchors.fill: parent;
                    hoverEnabled: true
                    onClicked: {
                        comboBox.state = ""
                        var preSelection = chosenItemText.text
                        chosenItemText.text = modelData
                        if(chosenItemText.text != preSelection){
                            comboBox.comboClicked();
                        }
                        listView.currentIndex = index;
                    }
                    onEntered: mouseMoveHighLight.opacity = 0.5;
                    onExited: mouseMoveHighLight.opacity = 0;
                }
            }
            highlight: Rectangle {
                width:listView.width;
                height:comboBox.height;
                color: "green";
                radius: 4
            }
        }
        MouseArea{
            anchors.fill: dropDown
            hoverEnabled: true
            onExited: {
                if(!containsMouse)
                    comboBox.state = "";
            }
        }
    }
 
    states: State {
        name: "dropDown";
        PropertyChanges { target: dropDown; height:30*comboBox.items.length+4 }
    }
 
    transitions: Transition {
        NumberAnimation { target: dropDown; properties: "height"; easing.type: Easing.OutExpo; duration: 200 }
    }
}


备注

ComboBox原型参考自:点击打开链接


相关文章