需求:
单击默认为单选,按住Ctrl+点击为任意项多选,按住Shift+点击为连续项多选
分析:
1.点击时区分按键状态来进行不同的操作;
2.根据不同的操作修改列表项的选中状态。
在Qt Widgets框架中,点击事件的QMouseEvent可以通过modifiers函数获取点击时按键的状态。在QML中,MouseArea的clicked(MouseEvent mouse)信号传递的MouseEvent也有这个modifiers属性,只要在点击时通过该属性判断哪些按键按下了就能把操作区分开来。
此外,选项状态的修改我是借助Connections关联信号槽来实现的。单选时,信号通知别的选项取消选中;Ctrl多选时直接选中不用发信号,各自独立选中;Shift多选时把起点行到点击行间的全选中。
实现:(简单的Demo如下)
//MyListView.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
ListView {
id: control
//按住shift时,连续多选的起点
property int mulBegin: 0
//单选信号
signal checkOne(int idx)
//多选信号
signal checkMul(int idx)
Connections{
target: control
//单选时修改连选起点
onCheckOne: control.mulBegin=idx;
}
//截取超出部分
clip: true
//不要橡皮筋效果
boundsBehavior: Flickable.StopAtBounds
//Item间隔
spacing: 2
model: 20
delegate: Rectangle{
id: item_delegate
width: ListView.view.width
height: 30
//记录Item选中状态
property bool checked: false
border.color: "gray"
color: item_delegate.checked? "black" : "gray"
Connections{
target: control
onCheckOne: item_delegate.checked=(idx===index);
onCheckMul: {
//连续多选时,判断在起始点前还是后,然后把中间的选中
if(idx>control.mulBegin){
item_delegate.checked=(index>=control.mulBegin&&index<=idx);
}else{
item_delegate.checked=(index<=control.mulBegin&&index>=idx);
}
}
}
MouseArea{
id: item_mousearea
anchors.fill: parent
onClicked: {
//ctrl+多选,shift+连选,默认单选
switch(mouse.modifiers){
case Qt.ControlModifier:
item_delegate.checked=!item_delegate.checked;
break;
case Qt.ShiftModifier:
control.checkMul(index);
break;
default:
control.checkOne(index);
control.mulBegin=index;
break;
}
}
}
}
ScrollBar.vertical: ScrollBar {
}
}
//main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("GongJianBo 1992")
MyListView{
anchors.fill: parent
anchors.margins: 10
}
}