目录
一、对属性值使用 JavaScript 表达式
二、在 QML 中添加 JavaScript 函数
三、使用 JavaScript 文件
四、属性绑定中的 JavaScript
五、信号处理程序中的 JavaScript
六、将信号连接到 JavaScript 函数
七、启动执行 JavaScript
QML 提供的 JavaScript 主机环境可以运行有效的标准 JavaScript表达式,例如条件运算符、数组、变量设置和循环。除了标准的 JavaScript 属性之外,QML 全局对象还包括许多帮助程序方法,这些方法简化了构建 UI 和与 QML 环境的交互。
QML提供的JavaScript环境比Web浏览器中的环境更严格。例如,在 QML 中,您不能添加或修改 JavaScript 全局对象的成员。在常规 JavaScript 中,可以通过使用变量而不声明它来意外执行此操作。在 QML 中,这将引发异常,因此必须显式声明所有局部变量。请参阅 JavaScript 环境限制,了解从 QML 执行的 JavaScript 代码限制的完整描述。JavaScript 主机环境|Qt QML 6.4.1https://doc.qt.io/qt-6/qtqml-javascript-hostenvironment.html#javascript-environment-restrictions
QML文档的各个部分可以包含JavaScript代码:
属性绑定的主体。这些 JavaScript 表达式描述了 QML 对象属性之间的关系。当属性的依赖项更改时,该属性也会根据指定的关系自动更新。
信号处理程序的主体。每当 QML 对象发出相关信号时,都会自动计算这些 JavaScript 语句。
自定义方法的定义。在 QML 对象主体中定义的 JavaScript 函数成为该对象的方法。
独立的 JavaScript 资源 (.js) 文件。这些文件实际上与 QML 文档是分开的,但它们可以导入到 QML 文档中。导入文件中定义的函数和变量可用于属性绑定、信号处理程序和自定义方法。
一、对属性值使用 JavaScript 表达式
Item {
width: Math.random()
height: width < 100 ? 100 : (width + 50) / 2
}
二、在 QML 中添加 JavaScript 函数
import QtQuick
Item {
id: container
width: 320
height: 480
function randomNumber() {
return Math.random() * 360;
}
function getNumber() {
return container.randomNumber();
}
TapHandler {
// This line uses the JS function from the item
onTapped: rectangle.rotation = container.getNumber();
}
Rectangle {
color: "#272822"
width: 320
height: 480
}
Rectangle {
id: rectangle
anchors.centerIn: parent
width: 160
height: 160
color: "green"
Behavior on rotation { RotationAnimation { direction: RotationAnimation.Clockwise } }
}
}
三、使用 JavaScript 文件
// myscript.js
function getRandom(previousValue) {
return Math.floor(previousValue + Math.random() * 90) % 360;
}
import QtQuick
import "myscript.js" as Logic
Item {
width: 320
height: 480
Rectangle {
color: "#272822"
width: 320
height: 480
}
TapHandler {
// This line uses the JS function from the separate JS file
onTapped: rectangle.rotation = Logic.getRandom(rectangle.rotation);
}
Rectangle {
id: rectangle
anchors.centerIn: parent
width: 160
height: 160
color: "green"
Behavior on rotation { RotationAnimation { direction: RotationAnimation.Clockwise } }
}
}
四、属性绑定中的 JavaScript
import QtQuick 2.12
Rectangle {
id: colorbutton
width: 200; height: 80;
color: inputHandler.pressed ? "steelblue" : "lightsteelblue"
TapHandler {
id: inputHandler
}
}
任何 JavaScript 表达式(无论多么复杂)都可以在属性绑定定义中使用,只要表达式的结果是其类型可以分配给属性的值。但是,不建议使用复杂的绑定和副作用,因为它们会降低代码的性能、可读性和可维护性。
有两种方法可以定义属性绑定:最常见的方法在前面的示例中的属性初始化中显示。第二种(也是更罕见的)方法是从命令式 JavaScript 代码中为属性分配一个从 Qt.binding() 函数返回的函数,如下所示:
import QtQuick 2.12
Rectangle {
id: colorbutton
width: 200; height: 80;
color: "red"
TapHandler {
id: inputHandler
}
Component.onCompleted: {
color = Qt.binding(function() { return inputHandler.pressed ? "steelblue" : "lightsteelblue" });
}
}
五、信号处理程序中的 JavaScript
QML 对象类型可以发出信号以响应发生的某些事件。这些信号可以由信号处理程序函数处理,客户端可以定义这些函数以实现自定义程序逻辑。
假设由矩形类型表示的按钮具有 TapHandler 和文本标签。当用户按下按钮时,点击处理程序会发出其点击信号。客户端可以使用 JavaScript 表达式对处理程序中的信号做出反应。QML 引擎根据需要执行处理程序中定义的这些 JavaScript 表达式。通常,信号处理程序绑定到 JavaScript 表达式以启动其他事件或分配属性值。
import QtQuick 2.12
Rectangle {
id: button
width: 200; height: 80; color: "lightsteelblue"
TapHandler {
id: inputHandler
onTapped: {
// arbitrary JavaScript expression
console.log("Tapped!")
}
}
Text {
id: label
anchors.centerIn: parent
text: inputHandler.pressed ? "Pressed!" : "Press here!"
}
}
六、将信号连接到 JavaScript 函数
发出信号的 QML 对象类型还为其信号提供默认信号处理程序。但是,有时客户端希望在另一个 QML 对象发出信号时触发在 QML 对象中定义的函数。这种情况可以通过信号连接来处理。QML 对象发出的信号可以通过调用信号的方法并将 JavaScript 函数作为参数传递来连接到 JavaScript 函数。例
// script.js
function jsFunction() {
console.log("Called JavaScript function!")
}
import QtQuick 2.12
import "script.js" as MyScript
Item {
id: item
width: 200; height: 200
TapHandler {
id: inputHandler
}
Component.onCompleted: {
inputHandler.tapped.connect(MyScript.jsFunction)
}
}
七、启动执行 JavaScript
有时需要在应用程序(或组件实例)启动时运行一些命令性代码。虽然将启动脚本作为全局代码包含在外部脚本文件中很诱人,但由于 QML 环境可能尚未完全建立,这可能会有严重的限制。例如,某些对象可能尚未创建,或者某些属性绑定可能尚未建立。
QML 对象在其实例化完成时发出附加的信号。相应处理程序中的 JavaScript 代码在对象实例化后运行。因此,编写应用程序启动代码的最佳位置是顶级对象的处理程序,因为此对象在完全建立 QML 环境时发出。
import QtQuick 2.0
Rectangle {
function startupFunction() {
// ... startup code
}
Component.onCompleted: startupFunction();
}
QML 文件中的任何对象(包括嵌套对象和嵌套的 QML 组件实例)都可以使用此附加属性。如果在启动时要执行多个处理程序,则它们将按未定义的顺序顺序运行。onCompleted()
同样,每个在被摧毁之前都会发出一个 destruction() 信号