由于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原型参考自:点击打开链接