有没有一种方法可以在QML WorkerScript中运行C++?

3
我有一个缓慢的I/O操作,需要从QML UI控制。I/O接口是用C++编写的。当用户按下按钮时,我需要发送消息并从设备获取响应。我希望用户能够在等待响应的同时做其他事情。WorkerScript似乎是实现这一需求最简单的方法,但如何将我的C++接口传递到脚本中,因为普通的QDeclarativeContext不能进入线程?是否有一种方法将C++导入到QML的JavaScript中?我甚至不需要在主线程中维护C++上下文,我可以让它完全存在于工作线程中,并且只通过传递消息来回传递信息。
编辑:
澄清:@dtech的答案满足了我当前的需求,但我仍然想知道问题的答案:是否可能将C++(即使不是有状态的)导入到WorkerScript中。
1个回答

3
为什么不选择将QObject放入专用线程中,执行代码而不阻塞主线程,并异步地与QML通信和传递结果呢?您不需要WorkerScript,也不是其预期使用方式。并且由于您的代码已经是C++,所以您只需要QThread和QObject。以下是一个简单的示例:
class Worker : public QObject {
    Q_OBJECT
  public slots:
    void doWork() {
      int i = 0;
      while (i < 100) {
        result(i++);
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
      }
    }
  signals:
    void result(int r);
};

class Controller : public QObject {
    Q_OBJECT
  public:
    Controller() {
      w = new Worker;
      t = new QThread;
      w->moveToThread(t);
      connect(this, SIGNAL(start()), w, SLOT(doWork()));
      connect(w, SIGNAL(result(int)), this, SIGNAL(result(int)));
      t->start();
    }
  private:
    Worker * w;
    QThread * t;
  signals:
    void start();
    void result(int r);
};

// in main.cpp
  Controller cw;
  engine.rootContext()->setContextProperty("Work", &cw);
  engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); // load main qml


// QML

  Column {
    Button {
      id: start
      onClicked: Work.start()
    }
    Text {
      id: res
    }
  }

  Connections {
    target: Work
    onResult: res.text = r
  }

这是一个简单的阻塞工作者,它将阻塞其线程约50秒,但仍能发出结果,在保持GUI线程空闲的同时更新QML端。请注意,一旦调用工作函数,就无法以任何方式中断、暂停或控制它,如果需要,您将需要实现非阻塞工作者。还需要一个C++控制器作为QML和“线程对象”之间的中介,因为似乎QML不能直接与这些对象配合使用。

@GrecKo - 如果你仔细阅读问题的前几个单词,你会意识到这不是一个“一次性任务”。这正是需要使用线程对象的情况 - io控制器。 - dtech
从问题中并不是很清楚,我提供一个替代方案。 - GrecKo
@GrecKo,“我需要从QML UI控制”的哪个部分不清楚? - dtech
1
@GrecKo请发布一个功能性的答案。 - dtech
1
不是的,工作脚本不能触及外部任何内容。它仅用于当您有自包含的重型JS时。在您的情况下,它将毫无用处。 - dtech
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接