Em um aplicativo de telefone Ubuntu, preciso executar alguma lógica quando ocorre um evento. Como não quero poluir o QML com muitas linhas de JavaScript, criei uma classe em um arquivo externo e conectei o sinal a um de seus métodos:
Principal.qml
import QtQuick 2.0
import Ubuntu.Components 1.1
import "action.js" as ActionJs
MainView {
objectName: "mainView"
applicationName: "example.cos64"
useDeprecatedToolbar: false
width: units.gu(20)
height: units.gu(20)
Page {
Button {
id: clickMeButton
text: "Click me"
onClicked: {
console.log('clicked');
}
Component.onCompleted: {
var action = new ActionJs.Action();
clickMeButton.clicked.connect(action.handleClick)
}
}
}
}
ação.js
function Action() {
this.handleClick = function() {
console.log('handleClick');
this.process();
}
this.process = function() {
console.log('processing...')
}
}
Funciona, mas não consigo chamar nenhum outro método do slot:
Starting /usr/lib/x86_64-linux-gnu/qt5/bin/qmlscene...
qml: clicked
qml: handleClick
file:///home/co64/projects/ubuntu/Example/action.js:5: TypeError: Property 'process' of object [object Object] is not a function
Por que o 'processo' não é reconhecido como uma função? Estou fazendo algo errado?
Responder1
Acredito que o problema imediato é que o contexto muda dentro das definições de função dentro de Action
. O this
objeto dentro Action.handleClick()
é Action.handleClick
, não Action
.
Mas vamos voltar um pouco: por que você está usando o paradigma função dentro de uma função aqui? Isso é comum no Javascript do navegador, já que não há namespace nesse ambiente. Para evitar atropelar outras funções, você falsifica um namespace criando um objeto para armazenar todas as suas funções.
No entanto, QMLfazfaça namespace. Observe que você teve que fazer referência Action
a ActionJS.Action
partir do arquivo QML. Portanto, não há necessidade de implementar outro namespace para suas funções; basta colocá-los no nível superior do arquivo JS:
function handleClick() {
console.log("handleClick");
process();
}
function process() {
console.log("processing...");
}
Então, no seu arquivo QML, faça
Component.onCompleted: {
clickMeButton.clicked.connect(ActionJS.handleClick)
}
Ou apenas
onClicked: ActionJS.handleClick()
Estou assumindo aqui que você realmente não precisa de um Action
objeto para nada além de namespace. Se você fizer isso, você deve aprender sobreprotótipo. Você também pode querer saber sobre.pragma library
, se você pretende usar esse arquivo JS em vários arquivos QML.