在QML中可以使用现有的QML元素来创建页面,但QML紧密的集成了必要的JavaScript。
但QML中使用JavaScript比较严格,在QML中不可以添加或修改JavaScript全局对象成员,这样可能会使用一个未经声明的变量。
内联JavaScript
一些小型的JavaScript函数可以和其他QML声明写在QML组件中。
Item{
anchors.fill:parent
id:item1
function text1(){ //创建一个函数
console.log("新的函数运行")
}
MouseArea{
anchors.fill: parent
onPressed:{
item1.text1()
}
}
}
使用JavaScript文件:
大量的JavaScript代码需要写在一个独立的文件中。使用import 来导入到QML中
新建一个Js文件:
点击左上角新建文件,选择Qt中的JsFile
输入完文件名后,在文件中添加以下代码:
在qml文件中导入Js文件:
导入JS文件格式:
import "name.js" as xxxx
name为文件名
xxxx为限定符,每一个JS文件的限定符必须唯一,限定符和JS之间是一对一映射
导入JS文件:
import QtQuick 2.9
import "MyJS.js" as Logic //导入Js文件 Logic为访问Js文件的对象
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea{
anchors.fill: parent
onPressed:{
Logic.func()//使用函数
}
}
}
代码隐藏实施文件
大多数JS文件被导入一个QML文件是有状态的,它们经常作为该QML文件的逻辑实现。这种情况下,为了使QML组件的实例有正确的行为,每一个实例都需要有JS对象和状态的一个独立的备份,导入JS文件时的默认行为时为每一个QML组件实例提供一个唯一的、独立的备份,JS代码和QML组件运行在相同的范围,因此可以访问和操作对象的声明属性。
无状态的JavaScript库
如果JS文件中的函数只用来提供输入和计算输出,不会直接操作QML组件实例,这种可以把该文件设为无状态(以免每一个QML对象都有这些库的拷贝,造成资源浪费)
使用pragma来指明一个特定文件是无状态库。
- pragma必须在所有有效的代码之前
- .pragma 库文件无法直接访问 QML 组件实例对象或属性
- QML 值可以作为函数参数传递
JS文件:
.pragma library
function func(x) {
console.log(x)
}
QML文件:
import QtQuick 2.9
import "MyJS.js" as Logic
import QtQuick.Window 2.2
Window {
id:window1
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea{
anchors.fill: parent
onPressed:{
Logic.func(window1.width)//传入window1的宽
}
}
}
从另一个JavaScript资源导入JavaScript
使用Qt.include()函数来导入其他文件,会将所有的函数 ,导入到当前的命名空间中(目前已逐渐被弃用)
使用Qt.include()函数导入
//myJs1.js
function func() {
console.log("func函数")
}
//textJs.js
Qt.include("MyJS.js")//导入MyJs.js文档
function showText() {
console.log("showText函数")
}
//qml
import QtQuick 2.9
import "textJs.js" as Logic //导入textJs.js文件
import QtQuick.Window 2.2
Window {
id:window1
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea{
anchors.fill: parent
onPressed:{
Logic.showText()//调用showText函数
Logic.func()//调用func函数
}
}
}
在程序启动时运行JavaScript
有时需要在应用程序(或组件实例)启动时运行一些命令性代码。虽然将启动脚本作为全局代码包含在外部脚本文件中很诱人,但由于 QML 环境可能尚未完全建立,这可能会有严重的限制。例如,某些对象可能尚未创建,或者某些属性绑定可能尚未建立。
- 使用Component元素提供的onCompleted属性,可以用来在QML环境完全建立后切换到启动脚本代码的执行。
- 每次销毁时会发出一个destruction()信号
Rectangle{
function func1(){
//一些操作
}
Component.onCompleted: {
func1()
}
}
属性绑定和属性赋值
- QML中使用<属性:值>的方式来创建属性绑定 (绑定的话会跟着更新)
- JavaScript使用<属性=值>的方式创建属性赋值 (赋值的话不会自动更新)会破环绑定
属性绑定:
Rectangle {
id:rect1
width: 100
height: 100
focus: true
color: "red"
Keys.onSpacePressed: {
rect1.width-=10
rect1.height-=10
}
}
Rectangle {
id:rect2
x:100
width: rect1.width //绑定了rect1的宽
height: rect1.height//绑定了rect1的高
color: "blue"
}
属性赋值:
具有绑定的属性会根据需要自动更新。但是,如果稍后从 JavaScript 语句为该属性分配静态值,则将删除绑定。
Rectangle {
width: 100
height: width * 2
color: "red"
focus: true
Keys.onSpacePressed: {
height = width * 3//会破坏绑定
//height = Qt.binding(function() { return width * 3 })
}
}
矩形的形状为:100 300
QML信号中的JavaScript
- 使用connect()函数,将QML信号关联到JavaScript上
- 可以在信号处理函数中直接调用JavaScript函数
使用connect()函数,将QML信号关联到JavaScript上:
Rectangle {
width: 100
height: width * 2
color: "red"
focus: true
MouseArea{
anchors.fill:parent
id:mouse1
}
Component.onCompleted: {
mouse1.clicked.connect(Logic.showText)//关联到Javascript中
}
}
信号处理函数中直接调用JavaScript函数:
Rectangle {
width: 100
height: width * 2
color: "red"
focus: true
MouseArea{
anchors.fill:parent
id:mouse1
onPressed: {
Logic.showText()//直接调用函数
}
}
}
JavaScript在QML中的限制:
在文件中编写的JavaScript代码无法修改全局对象,在 QML 中,全局对象是常量 - 不能修改或删除现有属性,也不能创建新属性。
违法操作:
a = 1;
for (var ii = 1; ii < 10; ++ii)
a = a * ii;
console.log("Result: " + a);
但可以简单的修改为法典:
var a = 1;
for (var ii = 1; ii < 10; ++ii)
a = a * ii;
console.log("Result: " + a);
全局代码在缩小的范围内可以使用 ,在启动期间,如果 QML 文件包含带有“全局”代码的外部 JavaScript 文件,则会在仅包含外部文件本身和全局对象的作用域中执行该文件。也就是说,它无法通常的访问 QML 对象和属性
允许仅访问脚本局部变量的全局代码:
var colors = [ "red", "blue", "green", "orange", "purple" ];
访问 QML 对象的全局代码将无法正常运行:
var initialPosition = { rootObject.x, rootObject.y }
目前在QML中this值是未定义的,使用id访问
Item {
width: 200; height: 100
function mouseAreaClicked(area) {
console.log("Clicked in area at: " + area.x + ", " + area.y);
}
MouseArea {
id: area
y: 50; height: 50; width: 200
onClicked: mouseAreaClicked(area)
//错误使用:
//onClicked: mouseAreaClicked(this)
}
}
参考文档: