从线程应用程序中的QtScript调用的Qt插槽
Qt slots called from QtScript in a threaded application
我通过创建一个派生的QThread类使我的应用程序可编写脚本,我在其中添加了多个QObject类,以便通过命令行访问它们的函数。
void commandLine::addObject(QObject *obj, QString name)
{
QScriptValue sv = m_scriptEngine.newQObject(obj);
m_scriptEngine.globalObject().setProperty(name, sv);
qObjectMap.insert(std::pair<QString, QObject *>(name, obj));
}
在 run(( 调用之后,类进入无限循环,使用 m_scriptEngine 来计算输入的每个命令行。
在我的(简化(主中,我做:
simuCLI cli;
simuCore core;
cli.addObject(&core, "core");
simuUI ui;
connect(&ui, SIGNAL(start()), &core, SLOT(start()));
但是当我从我的GUI和脚本调用start((时,结果是不同的
我的应用程序架构如下所示:
核心 -> 状态机 -> 机器 -> 通信
从 UI 开始效果很好。
从命令行开始执行代码,但不要启动 QStateMachine,它会发出信号,但永远不会接收它们。
Communication
通过发出Machine
中接收到的信号向Machine
发送命令。如果我从我的 UI 调用 core::start(( 它就可以工作如果我使用命令行调用 core::start(( 信号会发出但从未收到。
void WL::WL()
{
std::cout << "wl cst" << std::endl;
mLectMotStateMachine.setInitialState(sNoCard);
mLectMotStateMachine.start();
}
void WL::enterNoCard()
{
std::cout << "no card" << std::endl;
}
输出 :
从 UI 开始((:
wl cst
no card
从命令行开始((:
wl cst
如您所见,状态机永远不会进入它的第一个状态,就像它永远不会启动一样。
所以我的问题是:
1 - 如果我从命令行调用它,线程正在执行 start(( ?
2 - 如何调试信号?(我找到的最佳答案(
3 - 有没有办法在执行时一次查看每个信号连接 't'
4 - 我怎么知道我在哪个线程中执行?
5 - 您是否知道为什么我的代码仅在使用命令行时才不起作用?
您的问题是,在驻留在其他线程中的对象中直接调用线程不安全的方法是一个错误。我假设simuCore
对象是一个QThread
,并在其线程中创建一堆其他对象。这些对象不能直接从其他线程访问,除非您使它们的方法线程安全(您显然不会(。
答案是:
-
你可以检查一下。在
start()
方法中,添加:qDebug() << QThread::currentThread();
你会看到它与
qApp->thread()
是同一个线程,也称为主线程或 gui 线程。 -
我不知道你说的调试信号是什么意思。信号槽机制显然有效,那么有什么要调试的呢?
-
你为什么需要它?您是建立(和断开(连接的人,因此您当然可以在建立和断开这些连接的位置添加调试输出。没有魔法。
-
QThread::currentThread()
. -
因为你是:
-
从对象所在的线程以外的线程调用线程不安全的方法。
-
在你不应该的时候从
QThread
派生。
相反,您应该简单地将脚本引擎对象移动到普通专用
QThread
(无子类化(,并使用线程安全方法调用来评估命令行。信号槽连接是线程安全的,QMetaObject::invokeMethod
. -
例如:
#include <QCoreApplication>
#include <QScriptEngine>
#include <QThread>
class ScriptEngine : public QScriptEngine {
Q_OBJECT
Q_SIGNAL void evaluateSignal(const QString &);
public:
Q_SLOT void evaluate(const QString & str) { QScriptEngine::evaluate(str); }
/// A thread-safe evaluate()
Q_SLOT void safeEvaluate(const QString & str) { emit evaluateSignal(str); }
explicit ScriptEngine(QObject * parent = 0) : QScriptEngine(parent) {
connect(this, &ScriptEngine::evaluateSignal, this, &ScriptEngine::evaluate);
}
};
class Thread : public QThread {
// A thread that's safe to destruct, like it ought to be
using QThread::run; // final
public:
~Thread() { quit(); wait(); }
};
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
ScriptEngine engine;
Thread worker;
engine.globalObject().setProperty("qApp", engine.newQObject(qApp));
engine.moveToThread(&worker);
worker.start();
QMetaObject::invokeMethod(&engine, "evaluate", Q_ARG(QString, "print('Hi!')"));
engine.safeEvaluate("print('And hello!')");
engine.safeEvaluate("qApp.quit()");
return app.exec();
}
#include "main.moc"
- 如何在qt中从另一个类调用函数
- 使用Qt框架在c ++类中创建API调用
- 如何从其他类n个Qt C++调用QTimer?
- 在从Qt调用的Python脚本中导入OpenCV崩溃
- 如何从qml Keys.oPressed调用qt keyPressEvent(QKeyEvent*事件)
- 从第二个线程调用Qt信号有效 - >对连接的插槽没有影响
- 如何调用QT快速2扩展插件的方法
- Customplaceholder没有用于调用QT标签的匹配函数
- 无法在 QML 列表视图中调用 Qt c++ 方法
- 从QTCreator中调用QT的Fortran代码
- 使用QVariant调用Qt方法
- 从Javascript端调用Qt函数(QWebView)
- 从另一个 std::thread 调用 Qt 对象方法
- 在接收器对象销毁时未调用Qt disconnectNotify()
- 从Javascript代码中调用Qt函数
- C++接口类导致函数调用(Qt)不明确
- Marshal调用Qt主线程
- 当鼠标进入窗口时调用Qt mousePressedEvent
- 检索用户选择的结果作为调用Qt中外部程序的输入
- 只有当两个信号都发出时才调用Qt -调用槽