2017-08-18 3 views
0

J'ai un BusyIndicator qui doit tourner pendant les calculs lourds et s'arrêter lorsque les calculs sont terminés. Je pensais WorkerScript était la bonne voie à suivre mais from here, il semble que le secondaire (thread de calcul) dans le fichier .js n'a pas accès aux objets du thread primaire .qml.Accès WorkerScript à la classe Contrôleur

Ceci est problématique car tous mes calculs sont effectués via un QObject défini par le contrôleur C++ instancié par le thread primaire.

Voici mon code:

main.qml

import QtQuick 2.7 
import QtQuick.Layouts 1.3 
import QtQuick.Window 2.2 
import QtQuick.Controls 2.2 
import QtQuick.Controls.Material 2.0 
import QtQuick.Controls.Styles 1.2 
import QtQuick.Dialogs 1.2 

import LcQml 1.0 

ApplicationWindow 
{ 
    id: window 

    UiController 
    { 
     id: uiController 
    } 

    WorkerScript 
    { 
     id: importScanWorkerScript 
     source: "importScanWorkerScript.js" 
     onMessage: 
     { 
      busyIndicator.running = false; 
     } 
    } 

    FileDialog 
    { 
     id: importScanDialog 
     visible: false 
     title: "Import a [scan] file" 
     folder: "MyScannedScenesFolder" 
     nameFilters: [ "STL files (*stl)" ] 
     selectedNameFilter: "STL files (*stl)" 
     onAccepted: 
     { 
      importScanWorkerScript.sendMessage({'filepath': importScanDialog.fileUrl}) 
      busyIndicator.running = true; 
     } 
    } 

    BusyIndicator 
    { 
     id: busyIndicator 
     running: false 
     anchors.centerIn: parent 
    } 
} 

importScanWorkerScript.js

WorkerScript.onMessage = function(message) 
{ 
    uiController.onImportScanDevMenuClicked(message.filepath); 
    WorkerScript.sendMessage() 
} 

Pb: uiController ne définit pas importScanWorkerScrip t.js. Dois-je comprendre que WorkerScript ne peut gérer que des situations simples?

Répondre

1

Comme vous l'avez déjà remarqué, WorkerScript ne peut pas accéder aux contrôles de l'interface utilisateur. Mais votre thread séparé peut "parler" au thread principal de l'interface utilisateur en utilisant des messages. Quant à moi, cela fonctionne exactement comme dans tous les autres langages/frameworks. Envoyez simplement un message à partir du thread chaque fois que vous souhaitez mettre à jour l'interface utilisateur ou votre objet. Par exemple:

WorkerScript.onMessage = function(message) { 
    WorkerScript.sendMessage({ 'action': 'start' }) 
    // do some heavy task here 
    WorkerScript.sendMessage({ 'action': 'finish', 'data': somedata }) 
} 

et donc votre principale QML peut ressembler à ceci:

WorkerScript { 
    id: myWorker 
    source: "func.js" 
    onMessage: { 
     switch(messageObject.action) 
     { 
     case 'start': 
      spinner.running = true; 
      uiController.doSomething(); 
      break; 
     case 'finish': 
      spinner.running = false; 
      uiController.doSomethingAnother(); 
      break; 
     } 
    } 
} 
+0

Avec votre proposition, la uiController.doSomething() et uiController.doSomethingAnother() sont traités dans le thread d'interface utilisateur, pas ? Dans mon cas, il s'avère que uiController.doSomething() et uiController.doSomethingAnother() sont les fonctions lourdes réelles qui devraient être l'ordinateur dans le fil d'arrière-plan ... – arennuit

+0

Ah, ok, maintenant je le vois. La meilleure approche consiste à exécuter la tâche lourde à l'aide de QThread dans le code C++. Il n'y a aucun sens à exécuter une tâche C++ avec du code Javascript, bien que vous ne puissiez pas passer votre objet dans WorkerScript. – folibis

+0

Je ne suis pas sûr de comprendre que le chier WorkerScript est utile pour ... Qui veut effectuer une commutation lourde en js? En tout cas merci beaucoup pour votre aide! – arennuit