有没有办法从QML工作脚本运行C++

Is there a way to run C++ from a QML WorkerScript?

本文关键字:脚本 运行 C++ 工作 QML 有没有      更新时间:2023-10-16

我有一个缓慢的 I/O 操作,我需要从 QML UI 进行控制。 I/O 接口处于C++状态。 基本上,当用户按下按钮时,我需要发送消息并从设备获得响应。 我希望用户能够在等待响应时执行其他操作。 WorkerScript 似乎是实现这一目标的最简单方法,但是由于正常的 QDeclarativeContext 不会传递到线程中,我如何将我的C++接口放入脚本中? 有没有办法将C++导入QML的javascript? 我什至不需要在主线程中维护C++上下文,我可以完全在 worker 中生活,只需来回传递消息。
编辑:
澄清:@dtech的回答满足了我目前的需求,但我仍然想知道问题的答案:是否有可能将C++(即使不是有状态的)放入 WorkerScript。

当您可以选择将QObject放入专用线程,在不阻塞主线程的情况下执行代码,以及异步地将结果来回通信和交付给 QML 时,为什么要这样做?

你不需要WorkerScript,这也不是它的预期用途。而且由于您的代码无论如何都是C++的,因此您所需要的只是 QThreadQObject .

下面是一个简单的示例:

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 秒,但仍然能够发出将在 QML 端更新的结果,同时保持 GUI 线程空闲。 请注意,一旦调用了工作函数,就不可能以任何方式中断、暂停或控制它,如果需要,您必须实现非阻塞工作线程。也不需要C++控制器作为QML和"线程对象"之间的中介,因为QML似乎不能直接与这些对象相处。