- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个最小的 QT GUI 示例,以根据 QThread 5.12 documentation 中推荐的方法从工作线程更新小部件。 .
如 QThread 5.12 documentation 中所述,Worker 类(具有可能很长的 void doWork(const QString ¶meter) 方法是:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
对应的Controller类是:
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
与 QThread
的子类不同,文档中显示的方法显示了使用 Controller 和扩展 QObject
而不是扩展 QThread 和重写 QThread::run
方法,但是它没有说明如何在真实示例的上下文中使用这些方法。
我需要使用 QT Worker 线程来使用计时器更新 GUI 上的小部件。
我还需要能够使用不同的参数停止和重新启动/重新启动该线程,但我在如何正确执行此操作方面遇到了一些问题。指示通过 Controller 和 Worker 执行此操作的首选方法,但连接逻辑有点困惑。
我需要帮助的地方是如何将计时器正确地集成到我的工作线程中,以及如何在当前工作线程完成或被中断并重新启动时停止并重新启动替代工作线程。
我的工作代码由以下文件组成。
Controller .h
#pragma once
// SYSTEM INCLUDES
#include <QObject>
#include <QThread>
// APPLICATION INCLUDES
#include "Worker.h"
// DEFINES
// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STRUCTS
// TYPEDEFS
// FORWARD DECLARATIONS
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller(/*MainWindow* mainWindow*/) {
auto worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &) {
// how do I update the mainWindow from here
}
signals:
void operate(int);
};
worker .h
#pragma once
// SYSTEM INCLUDES
#include <QTimer>
#include <QObject>
#include <QEventLoop>
// APPLICATION INCLUDES
#include "Worker.h"
// DEFINES
// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STRUCTS
// TYPEDEFS
// FORWARD DECLARATIONS
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(int count) {
QString result = "finished";
// Event loop allocated in workerThread
// (non-main) thread affinity (as moveToThread)
// this is important as otherwise it would occur
// on the main thread.
QEventLoop loop;
for (auto i=0; i< count; i++) {
// wait 1000 ms doing nothing...
QTimer::singleShot(1000, &loop, SLOT(quit()));
// process any signals emitted above
loop.exec();
emit progressUpdate(i);
}
emit resultReady(result);
}
signals:
void progressUpdate(int secondsLeft);
void resultReady(const QString &result);
};
MainWindow.h - 我需要在此处添加一个 Controller
成员。我还在此处添加了一个 updateValue 插槽,我希望在其中更新 GUI。不幸的是,我不知道如何让 Controller 或工作人员连接
来自线程的信号以更新此插槽。
#pragma once
// SYSTEM INCLUDES
#include <memory>
#include <QMainWindow>
// APPLICATION INCLUDES
// DEFINES
// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// STRUCTS
// TYPEDEFS
// FORWARD DECLARATIONS
namespace Ui {
class MainWindow;
}
class Controller;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void updateValue(int secsLeft);
private:
Ui::MainWindow *ui;
std::unique_ptr<Controller> mpController;
};
主窗口.cpp -
#include <QThread>
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "Controller.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, mpController(std::make_unique<Controller>())
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
emit mpController->operate(100);
}
void MainWindow::updateValue(int secsLeft)
{
ui->secondsLeft->setText(QString::number(secsLeft));
}
最后是 main.cpp
#include "MainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
我基本上需要有关如何使用集成在我的 GUI 中的 QT 线程 Controller /工作器的帮助和解释。
最佳答案
我会尽力回答您在问题中提出的所有问题:
I don't know how to get the controller or the worker to connect a signal from the thread to update this slot.
你自己几乎是对的。
您的 Worker 位于 Controller 的事件循环中:
+--GUI-thread--+ (main event loop)
| MainWindow, |
| Controller --o-----> +--QThread--+ (own event loop in ::exec())
+--------------+ | Worker |
+-----------+
Controller 和 Worker 之间的通信必须通过信号槽连接进行。在 MainWindow 和 Controller 之间,信号有助于将依赖性降至最低。
您可以将 Controller 想象成一种中继:来自 MainWindow 的命令通过 Controller 转发给 Worker。 Worker 的结果通过 Controller 转发给任何感兴趣的人。
为此,您可以简单地在 Controller 中定义信号:
class Controller : public QObject
{
//...
signals:
void SignalForwardResult(int result);
};
然后代替
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
使用新信号:
connect(worker, &Worker::resultReady, this, &Controller::SignalForwardResult);
// Yes, you can connect a signal to another signal the same way you would connect to a slot.
并在您的 MainWindow
构造函数中:
//...
ui->setupUi(this);
connect(mpController, &Controller::SignalForwardResult, this, &MainWindow::displayResult);
同样适用于 Worker::progressUpdate()
-> Controller::SignalForwardProgress()
-> MainWindow::updateValue()
。
how to stop and restart a replacement worker when the current one has either finished or been interrupted and restarted.
或者为每个任务创建一个新的工作人员或者使用可以对新任务请求使用react的持久性工作人员。
::doWork()
函数来启动任务。resultReady
信号收到通知。QTimer
,您可以使用一个 cancel()
槽,因为它会在下一次超时之前在线程的事件循环中被调用。QAtomicInt
指针,但共享的 bool 通常也足够了。请注意,当方法在线程上运行时,该线程的事件循环会被阻塞,并且在该方法完成之前不会收到任何信号。
不要使用 QCoreApplication::processEvents()
除非你真的知道你在做什么。 (并期望你不这样做!)
how to properly integrate the timer in my worker thread
你不应该。
我猜你使用后台线程是因为有太多的工作要做,或者你需要阻塞等待太长时间以至于阻塞 GUI,对吧? (如果没有,请考虑不使用线程,为您省去很多麻烦。)
如果你需要一个计时器,让它成为Worker
的成员,并将它的parentObject设置为Worker实例。这样,两者将始终具有相同的线程关联。然后,将它连接到一个插槽,如 Worker::timeoutSlot()
。您可以在那里发出结束信号。
关于c++ - 在工作 GUI 示例中使用 Controller 和 QT Worker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54172976/
Yii::$app->runAction('new_controller/new_action', $params); 我相信这可以用来从另一个 Controller 调用 Controller Ac
这个问题类似于 this ,但我需要访问父成员(不是控制)。我不知道是否可以不使用依赖注入(inject)。 例如,我有一个父级,有一个成员调用用户,我需要从子 Controller 访问用户。 最佳
我有包含 2 个布局的根布局:- 选项面板- 绘制区域 我正在尝试的是访问 OptionsPaneController 中的 DrawAreaController 以调用其绘制方法。下面是 Optio
我的应用程序的 View Controller 层次结构设置如下: UIViewController | UITabBarController | UINavigationCo
我的应用程序的 View Controller 层次结构设置如下: UITabBarController | UINavigationController | | |
当我第一次为我目前在 Storyboard 中开发的应用程序创建基础布局时,我分两步完成: 选择我的 View Controller 并使用 Editor->Embed In->Navigation
设计要求: 显示用户可以选择的项目列表 选择一个项目后,使用后退按钮将用户带到一个新 View 。新 View 应在底部包含第一个屏幕中不存在的选项卡列表 单击选项卡中的项目时,应出现一个带有后退按钮
将父 Controller 设置为“parentCtrl as vm”,并将子 Controller 设置为“childCtrl as vmc”,以避免名称冲突,并且效果良好。 如何在子 Contro
我已经阅读了一些答案,例如关闭当前的 ViewController,但我的情况有所不同,因为我正在展示另一个 ViewController。 虽然我无法访问它的属性,但此代码显示了带有导航 Contr
如我所见,如果我们要实例化一个Model(例如,名为Post),我们只需调用: $post = new Post(); 现在,我还想实例化一个Controller(例如,名为Post,并为此 Cont
我已经疯狂地在整个网络上搜索解决我的问题的方法,但目前还没有。我的问题是我必须检查是否在 HTTP 请求中获得特定文本,该请求在一个 while 循环中,如果我这样做了,那么我应该离开循环并继续线程,
我想用this.get('controllers.pack.query');要得到App.PackQueryController在 App.PackController ,但失败了。 我认为问题是 E
我刚开始使用 Laravel。当我使用 codeigniter 或 zend 框架时,我可以将我的 Controller 组织到一个单独的目录中。例如,我可以创建“user/permission.ph
在 emberjs 前 2 我们可以从另一个 Controller 访问 Controller 或 Controller 中的任何方法 以下方式: App.get('router').get('nav
这可能是非常简单的实现,但我是 iOS 编程的新手,我似乎被卡住了。 所以,基本上,我有一个选项卡式应用程序。我决定除了标签栏之外还需要一个导航栏。为此,我放置了标签栏 Controller ,然后添
我有这个列表 Controller , define([ 'jquery', 'app' ], function ($,app) { app.controller("ListC
我有 3 个 Controller :RootController、FirstController 和 SecondController。我想从 RootController -> FirstCont
我有以下 Controller : /controllers/api/base_controller.rb /controllers/api/v1/articles_controller.rb 当为文
我是 Angular JS 的新手,尝试在另一个 Controller 中调用一个 Controller ,但出现以下错误。 ionic.bundle.js:21157 TypeError: $con
我有一个标签栏 Controller 和它的 3 个 child ,我还有另一个 View ,我制作了一个从 child 到 View Controller 的自定义转场,还有一个从 View Con
我是一名优秀的程序员,十分优秀!