如何在QML中定义Javascript资源

目录(?)[+]

在QML的设计中,在很多的情况下,我们可以把我们的逻辑代码通过JavaScript来书写,而且可以把我们的JS代码掩埋在我们的QML代码中,比如典型的代码如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Button {  
  2.     text: "Calculate"  
  3.     onClicked: {  
  4.         console.log("Change button is clicked")  
  5.         console.log(Method.factorial(10));  
  6.         console.log(Method.factorialCallCount())  
  7.     }  
  8. }  


在上面的代码中,我们定义了一个Button按钮.每当我们的按钮的触碰事件click发生时,我们可以在我们的QML文件中直接按照上面的方法来执行我们的Javascript代码.在onClicked后面的" "及" "中间其实就是我们的Javascript代码来实现我们的逻辑处理.

事实上,如果我们的逻辑比较复杂,并且有时,我们想把我们的逻辑及UI (由QML语言描述)分开的话,这时候,我们可以直接把我们的逻辑代码放入到一个叫做Javascript的文件之中.然后再在我们的QML文件中进行直接import.这样的好处是界面和逻辑分开,也可以使得我们的QML代码简单明了.

在QML中引入Javascript有两种方式.有兴趣的开发者可以参阅Qt的官方文档.在该文档中,如果不是自己亲手去实验,其实也很晦涩难懂.简单地说,这两种方式是:

  • stateful:在这种方式下,js模块中所定义的变量在每次被import后,都会被拷贝一份.所以如果有被多次import就有多个拷贝,而且每个的值都可能会有不同. 在这种过情况下,js文件可以直接访问在我们QML文件中所定义的object
  • statelss:在这种情况下,js所定义的模块就像一个公共分享的库一样.它里面的方法都可以被使用,并且模块里定义的变量在所以被import的QML代码中独一份,无论被import多少次.另外,它不可以直接访问QML文件中的object尽管可以通过参数的传人对所要求的object进行修改.

1)stateful


我们特意在我们的例子中加入我们一个特有的MyButton.qml:

MyButton.qml


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // MyButton.qml  
  2. import QtQuick 2.0  
  3. import "my_button_impl.js" as Logic // a new instance of this JavaScript resource is loaded for each instance of Button.qml  
  4. import "factorial.js" as Method  
  5.   
  6. Rectangle {  
  7.     id: rect  
  8.     width: 200  
  9.     height: 100  
  10.     color: "red"  
  11.     property int count: 0  
  12.     property alias text: mytext.text  
  13.     signal clicked()  
  14.   
  15.     Text {  
  16.         id: mytext  
  17.         anchors.centerIn: parent  
  18.         font.pixelSize: units.gu(3)  
  19.     }  
  20.   
  21.     MouseArea {  
  22.         id: mousearea  
  23.         anchors.fill: parent  
  24.         onClicked: {  
  25.             rect.clicked()  
  26.             count = Logic.onClicked(rect)  
  27.             console.log(Method.factorialCallCount())  
  28.         }  
  29.     }  
  30. }  

my_button_impl.js


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // this state is separate for each instance of MyButton  
  2. var clickCount = 0;  
  3.   
  4. function onClicked(obj) {  
  5.     clickCount += 1;  
  6.     if ((clickCount % 5) == 0) {  
  7.         obj.color = Qt.rgba(1,0,0,1);  
  8.     } else {  
  9.         obj.color = Qt.rgba(0,1,0,1);  
  10.     }  
  11.   
  12.     return clickCount;  
  13. }  
  14.   
  15. function changeBackgroundColor() {  
  16.     main.backgroundColor = "green"  
  17. }  

在我们的MyButton.qml中,我们import了my_button_impl.js这个文件.由于这个js文件的最前面没有".pragma library",所以它是一个stateful的Javascript.如果我们有多个MyButton的实例,那么每个按钮都分别有自己的clickCount变量,并且它们之间毫无关系.

我们在我们的Main.qml中加入两个我们设计的MyButton按钮:

Main.qml


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Column {  
  2.     anchors.centerIn: parent  
  3.     spacing: units.gu(5)  
  4.   
  5.     MyButton {  
  6.         anchors.horizontalCenter: parent.horizontalCenter  
  7.         text: "Button " + count  
  8.         onClicked: {  
  9.             console.log("Button 1 is clicked!")  
  10.         }  
  11.     }  
  12.   
  13.     MyButton {  
  14.         anchors.horizontalCenter: parent.horizontalCenter  
  15.         width: parent.width  
  16.         text: "Button " + count  
  17.         onClicked: {  
  18.             console.log("Button 2 is clicked!")  
  19.         }  
  20.     }  
  21.  }  

运行我们的代码:



从上面的输出可以看出,两个按钮的count可以是完全不同的.它们之间完全独立.

另外,我们也在我们的my_button_impl.js中设计了如下的函数:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. function changeBackgroundColor() {  
  2.     main.backgroundColor = "green"  
  3. }  

显然它可以直接访问我们在Main.qml中的object Main.运行我们应用,点击"Change color"按钮:



可以看见我们的MainView的背景颜色已经发生改变了.

2)stateless



针对这种情况,在Javascript文件的开头部分必须是一下的语句:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. .pragma library  

我们一个完整的factorial.js文件如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. .pragma library  
  2.   
  3. var factorialCount = 0;  
  4.   
  5. function factorial(a) {  
  6.     // a = parseInt(a);  
  7.   
  8.     // factorial recursion  
  9.     if (a > 0)  
  10.         return a * factorial(a - 1);  
  11.   
  12.     // shared state  
  13.     factorialCount += 1;  
  14.   
  15.     // recursion base-case.  
  16.     return 1;  
  17. }  
  18.   
  19. function factorialCallCount() {  
  20.     return factorialCount;  
  21. }  
  22.   
  23. function changeBackgroundColor() {  
  24.     main.backgroundColor = "green"  
  25. }  
  26.   
  27. function changeBackground(obj) {  
  28.     obj.backgroundColor = "green"  
  29. }  

在这个模块中,我们定义了一个factorialCount的变量.由于是stateless,所有这个变量对于所有的import文件来说,只有一个.有点类似于C++类中static变量.在我们的Main.qml中,我们定义了一个按钮:

Main.qml


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Button {  
  2.     text: "Calculate"  
  3.     onClicked: {  
  4.         console.log("Calculate button is clicked")  
  5.         console.log(Method.factorial(10));  
  6.         console.log(Method.factorialCallCount())  
  7.     }  
  8. }  

按下这个按钮,factorial将会帮我们计算我们的结果,同时会显示factorial被调用多少次.在我们的MyButton.qml中,我们也在点击的地方展示这个数据:

MyButton.qml


[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. MouseArea {  
  2.     id: mousearea  
  3.     anchors.fill: parent  
  4.     onClicked: {  
  5.         rect.clicked()  
  6.         count = Logic.onClicked(rect)  
  7.         console.log(Method.factorialCallCount())  
  8.     }  
  9. }  

如果我们点击"Calculate"按钮,在点击MyButton按钮,我们将可以看到同样的factorialCount值.



同样的,如果在我们的factorial.js中直接访问object main来修改它的属性,就像:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. function changeBackgroundColor() {  
  2.     main.backgroundColor = "green"  
  3. }  

这样是不可以的.我们必须通过如下的方法来修改:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. function changeBackground(obj) {  
  2.     obj.backgroundColor = "green"  
  3. }  

我们在我们的Main.qml中使用如下的代码来实现:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Button {  
  2.     text: "Change color via stateless "  
  3.     onClicked: {  
  4.         Method.changeBackground(main)  
  5.     }  
  6. }  

整个项目的源码: https://github.com/liu-xiao-guo/JsInQml

原文地址:http://blog.csdn.net/ubuntutouch/article/details/51451757
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值