QML事件
单击事件
1. QML编程中同样需要对鼠标键盘等事件进行处理。
2. 因为QML程序更多的是实现触摸式用户界面,所以更多的是对鼠标(在触屏设备上可能是手指)单击的处理与以前的窗口部件不同,
在QML中如果一个项目想要能够被单击,就要在其上放置一个MouseArea元素.
3. 用户只能在 MouseArea 确定的范围内进行单击。
1.01 MouseArea组件
1. MouseArea是一个不可见的项目,通常用来和一个可见的项目配合使用来为其提供鼠标处理。
2. MouseArea的enabled属性可以用来设置是否启用鼠标处理,值默认为true,如果设置为false,MouseArea对于鼠标事件将会变为透明的,不再处理任何鼠标事件。
3. pressed属性表明了用户在MouseArea是否按住了鼠标按钮,这个属性经常用于属性绑定,可以实现在鼠标按下时执行一些操作。
4. containsMouse属性表明了当前是否有鼠标光标在MouseArea, 只有鼠标的一个按钮处于按下状态才可以被检测到。
5. 鼠标位置和按钮单击等信息是通过信号提供的,可以使用事件处理器来获取,
最常用的有onClicked()、onDoubleClicked()、onPressed()、onReleased()和onPressAndHold()等。
6. MouseArea项目只报告鼠标单击而不报告鼠标光标的位置改变,这个可以通过设置hoverEnabled属性来进行更改。
这样 onPositionChanged()、onEntered()和onExited()等处理函数都可以使用了,而且这时containsMouse属性也可以在没有鼠标按钮按下的情况下进行检查了。
1.02 MouseEvent
1. 在MouseEvent对象中,可以通过x和y属性获取鼠标的位置.
2. 通过button属性可以获取按下的按键;通过modifiers属性可以获取按下的键盘修饰符等。
这里的button可取的值有Qt.LeftButton左键、Qt. RightButton 右键和 Qt. MiddleButton 中键;
而modifiers的值由多个按键进行位组合而成,在使用时需要将modifiers与这些特殊的按键进行按位与来判断按键,常用的按键有
Qt.NoModifier 没有修饰键、
Qt.ShiftModifier 一个 Shift 按键、
Qt.ControlModifier 一个 Ctrl 按键、
Qt.AltModifier一个 Alt按键。
Rectangle {
width: 100; height: 100
color: "green"
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
if (mouse.button == Qt.RightButton)
parent.color = 'blue';
else if ((mouse.button == Qt.LeftButton)
&& (mouse.modifiers & Qt.ShiftModifier))
parent.color = 'green';
else
parent.color = 'red';
}
}
}
1.03 拖 拽
1. MouseArea中的drag分组属性提供了一个使项目可以拖拽的简便方法。
2. drag.target属性用来指定拖动的项目的id;
3. drag.active属性获取项目当前是否正在被拖动的信息;
4. drag.axis属性用来指定属性拖动的方向,
水平方向(Drag.XAxis)、
垂直方向(Drag.YAxis)
两个方向都可以(Drag.XandYAxis);
5. drag.minimum 和 drag.maximum限制了项目在指定方向上拖动的距离。
Rectangle {
id: container
width: 600; height: 200
Rectangle {
id: rect
width: 50; height: 50
color: "red"
opacity: (600.0 - rect.x) / 600
MouseArea {
anchors.fill: parent
drag.target: rect
drag.axis: Drag.XAxis
drag.minimumX: 0
drag.maximumX: container.width - rect.width
}
}
}
1.04 按键处理
1. 当一个按键按下或者释放时,则产生一个键盘事件,并将其传递给获得有焦点的QML项。
2. 为了方便创建可重用的组件并解决一些实现流程的用户界面的独特问题,QML项目在Qt传统的键盘焦点模型上添加了基于作用域的扩展。
3. 所有的基于Item的可见元素都可以通过Keys附加属性来进行按键处理。
按键处理过程:
(1)Qt获取键盘动作并产生一个键盘事件。
(2)如果包含QDeclarativeView的Qt部件具有焦点,那么键盘事件会传递给它,否则将进行常规的按键处理。
(3)场景将键盘事件交付给具有活动焦点的QML项目。如果没有项目具有活动焦点,键盘事件会被忽略,然后继续常规的按键处理。
(4)如果具有活动焦点的QML项目接受了该键盘事件,那么传播将停止。
否则,该事件会递归的传递到每一个项目的父项目,直到被接受,或者到达根项目。
(5)如果到达了根项目,该键盘事件会被忽略而继续常规的Qt按键处理。
Rectangle {
width: 100; height: 100
focus: true
Keys.onPressed: {
if (event.key == Qt.Key_A) {
console.log('Key A was pressed');
event.accepted = true;
}
}
}
1.05 按键导航
1. KeyNavigation元素,它也是一个附加属性,
2. 可以用来实现使用方向键或者 Tab 键来进行项目的导航。
它的属性有backtab、down、left、priorityright、tab和up等。
import QtQuick 2.0
Grid {
width: 100; height: 100
columns: 2
Rectangle {
id: topLeft
width: 50; height: 50
color: focus ? "red" : "lightgray"
focus: true
KeyNavigation.right: topRight
KeyNavigation.down: bottomLeft
}
Rectangle {
id: topRight
width: 50; height: 50
color: focus ? "red" : "lightgray"
KeyNavigation.left: topLeft
KeyNavigation.down: bottomRight
}
Rectangle {
id: bottomLeft
width: 50; height: 50
color: focus ? "red" : "lightgray"
KeyNavigation.right: bottomRight
KeyNavigation.up: topLeft
}
Rectangle {
id: bottomRight
width: 50; height: 50
color: focus ? "red" : "lightgray"
KeyNavigation.left: bottomLeft
KeyNavigation.up: topRight
}
}
1.06 查询活动焦点项目
一个项目是否具有活动焦点,可以通过Item::activeFocus属性进行查询。
Text {
text: activeFocus? "I have active focus":"I do not have active focus"
}
1.07 获取焦点和焦点作用域
1. 项目可以通过设置其focus属性为true来使其获得焦点。
2. 一个可重用或者可被导人的组件时,简单地使用focus属性就不再有效。
3. 为了解决这个问题,在QML中引人了所谓的焦点作用域(focus scope)的概念,
一个焦点作用域通过FocusScope元素来创建。
// MyWidget.qml
import QtQuick 2.0
FocusScope {
// FocusScope需要绑定到子项目的可视属性上
property alias color: rectangle.color
x: rectangle.x; y: rectangle.y
width: rectangle.width; height: rectangle.height
Rectangle {
id: rectangle
anchors.centerIn: parent
color: "lightsteelblue"; width: 175; height: 25; radius: 10; smooth: true
Text { id: label; anchors.centerIn: parent }
focus: true
Keys.onPressed: {
if (event.key == Qt.Key_A)
label.text = 'Key A was pressed'
else if (event.key == Qt.Key_B)
label.text = 'Key B was pressed'
else if (event.key == Qt.Key_C)
label.text = 'Key C was pressed'
}
}
}
import QtQuick 2.0
Rectangle {
id: window
color: "white"; width: 240; height: 150
Column {
anchors.centerIn: parent; spacing: 15
MyWidget {
focus: true
color: "lightblue"
}
MyWidget {
color: "palegreen"
}
}
}
1.08 定时器
1. 定时器可以用来将一个动作在指定的时间间隔触发一次或者多次,在QML中使用Timer元素来表示一个定时器。
2. interval属性用来设置时间间隔,单位是毫秒,默认值是1000毫秒;
3. repeat属性用来设置是否重复触发,如果为false,则只触发一次并自动将running属性设置为false,其默认值为false;
4. running属性设置为true时将开启定时器,否则停止定时器,其默认值为false;当定时器触发时会执行onTriggered()信号处理函数.
Item {
Timer {
interval: 500; running: true; repeat: true
onTriggered: time.text = Date().toString()
}
Text { id: time }
}
1.09 动态加载可见的QML组件
1. Loader元素用来动态加载可见的QML组件,它可以加载一个QML文件。
2. 这个对于拖延组件的创建是很有用的:如:
当一个组件需要在要求的时候被创建;
由于性能原因一个组件不应该被创建时。
3. Loader和其他任何可见的项目一样,必须对其进行位置和大小的设置,这样它才能成为可见的。
Item {
width: 200; height: 200
Loader {
id: pageLoader
}
MouseArea {
anchors.fill: parent
onClicked: pageLoader.source='Page1.qml'
}
}
4. 任何从被加载的项目中发射的信号都可以使用Connections元素进行接收。
Item {
width: 100; height: 100
Loader {
id: myLoader
source: "MyItem.qml"
}
Connections {
target: myLoader.item
onMessage: console.log(msg)
}
}
5. Loader是一个焦点作用域,对于它的任何获得活动焦点的子项目, 都必须将focus属性设置为true。
任何在被加载的项目中的键盘事件也应该被接受,从而使它们不传播到 Loader。
Rectangle {
width: 200; height: 200
Loader {
id: loader
focus: true
}
MouseArea {
anchors.fill: parent
onClicked: loader.source = "KeyReader.qml"
}
Keys.onPressed: {
console.log("Captured:", event.text);
}
}
KeyReader.qml被加载完成,它便会接受键盘事件而且这里将event.accepted设置为了true,
这样事件就不会传播到父项目Rectangle中
Item {
Item {
focus: true
Keys.onPressed: {
console.log("Loaded item captured:", event.text);
event.accepted = true;
}
}
}