我在我的应用程序中使用Qt脚本引擎作为用户访问其功能的替代方法.因此,我将一些C++类导出到Qt ScriptEngine,它将作为应用程序的接口.问题是,这些C++类可以抛出异常.
我有一个"ScriptInterface"类在自己的线程上运行,侦听处理脚本的请求.因此,当我评估用户的脚本时,我有一个try/catch块来处理异常,并将错误打印到应用程序中的控制台.
...
try {
m_engine->evaluate(script, name);
}
catch (Exception const& e) {
// deal with it
}
catch (...) {
// scary message
}
Run Code Online (Sandbox Code Playgroud)
这在windows中完美运行...但在linux中不起作用 - 程序终止于此消息:
terminate called after throwing an instance of 'Basilisk::InvalidArgumentException'
what(): N8Basilisk24InvalidArgumentExceptionE
Aborted
Run Code Online (Sandbox Code Playgroud)
我有一种预感,因为异常冒泡到事件处理程序(因为脚本引擎使用信号来调用导出的类中的函数),所以我重新实现了QApplication :: notify,以处理那里的异常,但它们不是'抓住了.
我的问题是,我做了一些根本错误的事情吗?另外,作为替代方案,是否可以从我的C++类中显式抛出脚本异常?
提前致谢
编辑:修改说明以包含catch(...)语句.
更新(解决方案):我通过遵循类似于接受的答案中概述的策略来"修复"此问题.虽然我还没有找到为什么异常不会被linux捕获的原因(我现在怀疑是m_engine-> evaluate在linux上产生一个单独的线程),但我已经开始使用预期的异常抛出方式在Qt Scripts中,就是这样QScriptContext::throwError().
如果我的函数看起来像这样:(随机例子)
void SomeClass::doStuff(unsigned int argument) {
if (argument != 42) {
throw InvalidArgumentException(
"Not the answer to Life, the Universe and Everything.");
}
// function that …Run Code Online (Sandbox Code Playgroud) 我有一个程序使用QtScript进行一些自动化.我已经在脚本引擎的全局范围中添加了一堆C++函数和类,以便脚本可以访问它们,如下所示:
QScriptValue fun = engine->newFunction( systemFunc );
engine->globalObject().setProperty( "system", fun );
Run Code Online (Sandbox Code Playgroud)
我希望能够连续运行多个脚本,每个脚本都有一个全新的状态.因此,如果一个脚本设置了一个全局变量,比如
myGlobalVar = "stuff";
Run Code Online (Sandbox Code Playgroud)
我希望在下一个脚本运行之前擦除该变量.我这样做的方法是制作脚本引擎的全局对象的深层副本,然后在脚本完成运行时恢复它.但深拷贝不起作用,因为我的system功能突然出现错误:
TypeError: Result of expression 'system' [[object Object]] is not a function.
Run Code Online (Sandbox Code Playgroud)
这是我的深层复制功能,改编自:http:
//qt.gitorious.org/qt-labs/scxml/blobs/master/src/qscxml.cpp
QScriptValue copyObject( const QScriptValue& obj, QString level = "" )
{
if( obj.isObject() || obj.isArray() ) {
QScriptValue copy = obj.isArray() ? obj.engine()->newArray() : obj.engine()->newObject();
copy.setData( obj.data() );
QScriptValueIterator it(obj);
while(it.hasNext()) {
it.next();
qDebug() << "copying" + level + "." + it.name();
if( it.flags() & QScriptValue::SkipInEnumeration ) …Run Code Online (Sandbox Code Playgroud) QScriptEngine有evaluate()方法,可用于加载脚本,执行它并从已加载的脚本运行指定的函数.但是如何清除当前脚本并加载新脚本呢?例如,我使用evaluate()从文件加载脚本,然后使用evaluate()来获取脚本函数并调用它们.但是,如何清除当前脚本并从另一个文件加载新脚本呢?删除和创建QScriptEngine似乎是一个解决方案,但它喜欢在GUI线程中创建(由于QScriptEngineDebugger),而所有脚本操作都在单独的线程中执行.那么在不重新创建QScriptEngine对象的情况下清除当前脚本的方法是什么?
我试图用Visual Studio 2010(C++)编译QtScriptGenerator(gitorious)并遇到编译错误.在搜索解决方案时,由于VS2010实现STL和/或c ++ 0x一致性更改的变化,我偶尔会看到自VS2008以来引入的编译破坏的引用.
任何想法下面发生了什么,或者我如何解决它?如果有问题的代码似乎是QtScriptGenerator,我想我会更容易修复它..但在我看来,违规代码可能在VS2010的STL实现中,我可能需要创建一个变通方法?
PS.我对模板和STL非常不熟悉.我有嵌入式和控制台项目的背景,这些项目直到最近才被避免,以减少内存消耗和交叉编译器风险.
编辑 - 看起来可能是Visual Studio的std :: copy实现发生了变化.
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xutility(275) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'rpp::pp_output_iterator<_Container>' (or there is no acceptable conversion)
with
[
_Container=std::string
]
c:\qt\qtscriptgenerator\generator\parser\rpp\pp-iterator.h(75): could be 'rpp::pp_output_iterator<_Container> &rpp::pp_output_iterator<_Container>::operator =(const char &)'
with
[
_Container=std::string
]
while trying to match the argument list '(rpp::pp_output_iterator<_Container>, rpp::pp_output_iterator<_Container>)'
with
[
_Container=std::string
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xutility(2176) : …Run Code Online (Sandbox Code Playgroud) 当我调用此代码时:
QScriptEngine e;
e.evaluate("print('hello, world!')");
Run Code Online (Sandbox Code Playgroud)
输出文本(来自print方法)写入主应用程序的终端.
有没有办法将其重定向到自定义QIODevice?
我想制作一个非常基本的GUI:标签,文本区域.
但我想为我的标签着色,让它们在MAC,Windows和Linux上看起来总是一样.
所以,我尝试使用样式表:
QTabWidget::pane
{
border-top: 2px solid #1B1B1B;
background-color: #262626;
}
QTabWidget::tab-bar
{
left: 5px;
alignment: left;
background: #3E3E3E;
}
QTabBar::tab
{
background: transparent;
color: #757575;
padding: 15px 5px 15px 5px;
}
QTabBar::tab:hover
{
text-decoration: underline;
}
QTabBar::tab:selected
{
color: #DEF600;
background: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #262626, stop: 1.0 #3D3D3D );
}
Run Code Online (Sandbox Code Playgroud)
但即使选项卡看起来很好,也存在一个问题:选项卡窗格仍然是透明的......
我可以通过添加以下强制背景颜色:
QWidget
{
background-color: #262626;
}
Run Code Online (Sandbox Code Playgroud)
但是如你所知,这会改变所有小部件的背景颜色,甚至我的QPlainTextEdit仍然需要白色背景.而且更烦人的是,这会重置操作系统皮肤并显示丑陋的滚动条(我真的想保留它们).
有没有办法更改选项卡窗格背景而无需重新分配所有组件?
我尝试按照教程创建一个安装程序。然后,我根据 Qt Installer Framework 目录中的开始菜单示例添加了一个名为“installerscript.qs”的脚本。
“installscript.qs”如下:
/****************************************************************************
**
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
**
**
** open-editor to use.
** Copyright (C) 2018 os_sys-devlopment-group
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
** This program is distributed in the hope that it will be …Run Code Online (Sandbox Code Playgroud) 我正在将QScriptEngine代码迁移到QJSEngine,并且遇到了一个问题,我在评估脚本后无法调用函数:
#include <QCoreApplication>
#include <QtQml>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QJSEngine engine;
QJSValue evaluationResult = engine.evaluate("function foo() { return \"foo\"; }");
if (evaluationResult.isError()) {
qWarning() << evaluationResult.toString();
return 1;
}
if (!evaluationResult.hasProperty("foo")) {
qWarning() << "Script has no \"foo\" function";
return 1;
}
if (!evaluationResult.property("foo").isCallable()) {
qWarning() << "\"foo\" property of script is not callable";
return 1;
}
QJSValue callResult = evaluationResult.property("foo").call();
if (callResult.isError()) {
qWarning() << "Error calling \"foo\" function:" << …Run Code Online (Sandbox Code Playgroud)