![]() |
Home · All Classes · All Functions · Overviews |
QML encourages building UIs declaratively, using Property Binding and the composition of existing QML Elements. If imperative code is required to implement more advanced behavior, the Script element can be used to add JavaScript code directly to a QML file, or to include an external JavaScript file.
The Script element is a QML language intrinsic. It can be used anywhere in a QML file, except as the root element of a file or sub-component, but cannot be assigned to an object property or given an id. The included JavaScript is evaluated in a scope chain. The QML Scope documentation covers the specifics of scoping in QML.
A restriction on the JavaScript used in QML is that you cannot add new members to the global object. This happens transparently when you try to use a variable without declaring it, and so declaring local variables is required when using Java script in QML.
The global object in QML has a variety of helper functions added to it, to aid UI implementation. See QML Global Object for further details.
Note that if you are adding a function that should be called by external elements, you do not need the Script element. See Adding new methods for information about adding slots that can be called externally.
Small blocks of JavaScript can be included directly inside a QML Document as the body of the Script element.
Rectangle { Script { function factorial(a) { a = Integer(a); if (a <= 0) return 1; else return a * factorial(a - 1); } } }
Good programming practice dictates that only small script snippets should be written inline. QML prohibits the declaration of anything other than functions in an inline script block. For example, the following script is illegal as an inline script block as it declares the non-function variable lastResult.
// Illegal inline code block var lastResult = 0 function factorial(a) { a = Integer(a); if (a <= 0) lastResult = 1; else lastResult = a * factorial(a - 1); return lastResult; }
To avoid cluttering the QML file, large script blocks should be in a separate file. The Script element's source property is used to load script from an external file.
If the previous factorial code that was illegal as an inline script block was saved into a "factorial.js" file, it could be included like this.
Rectangle { Script { source: "factorial.js" } }
The source property may reference a relative file, or an absolute path. In the case of a relative file, the location is resolved relative to the location of the QML Document that contains the Script element. If the script file is not accessible, an error will occur. If the source is on a network resource, the enclosing QML document will remain in the waiting state until the script has been retrieved.
It is occasionally necessary to run a block of JavaScript code at application (or component instance) "startup". While it is tempting to just include the startup script as global code in an external script file, this can have severe limitations as the QML environment may not have been fully established. For example, some objects might not have been created or some Property Bindings may not have been run. QML Script Restrictions covers the exact limitations of global script code.
The QML Component element provides an attached onCompleted property that can be used to trigger the execution of script code at startup after the QML environment has been completely established.
The following QML code shows how to use the Component::onCompleted property.
Rectangle {
Script {
function startupFunction() {
// ... startup code
}
}
Component.onCompleted: startupFunction();
}
Any element in a QML file - including nested elements and nested QML component instances - can use this attached property. If there is more than one script to execute at startup, they are run sequentially in an undefined order.
QML Script blocks contain standard JavaScript code. QML introduces the following restrictions.
In QML, the global object is constant - existing properties cannot be modified or deleted, and no new properties may be created.
Most JavaScript programs do not explicitly modify the global object. However, JavaScript's automatic creation of undeclared variables is an implicit modification of the global object, and is prohibited in QML.
Assuming that the a variable does not exist in the scope chain, the following code is illegal in QML.
// Illegal modification of undeclared variable a = 1; for (var ii = 1; ii < 10; ++ii) a = a * ii; console.log("Result: " + a);
It can be trivially modified to this legal code.
var a = 1; for (var ii = 1; ii < 10; ++ii) a = a * ii; console.log("Result: " + a);
Any attempt to modify the global object - either implicitly or explicitly - will cause an exception. If uncaught, this will result in an warning being printed, that includes the file and line number of the offending code.
During startup, if a Script block includes an external file with "global" code, it is executed in a scope that contains only the external file itself and the global object. That is, it will not have access to the QML objects and properties it normally would.
Global code that only accesses script local variable is permitted. This is an example of valid global code.
var colors = [ "red", "blue", "green", "orange", "purple" ];
Global code that accesses QML objects will not run correctly.
// Invalid global code - the "rootObject" variable is undefined var initialPosition = { rootObject.x, rootObject.y }
This restriction exists as the QML environment is not yet fully established. To run code after the environment setup has completed, refer to Running Script at Startup.
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies) | Trademarks | Qt 4.7.0 |