- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
QScriptEngine
的默认print()
函数将结果打印到 Qt Creator IDE 的终端以进行调试。因此,如果我们要自己制作 ECMA 脚本解释器,则必须将输出重定向到我们的文本编辑器。
这部分文件"Making Applications Scriptable"自 Qt 4.3 以来保持不变。
Qt Script provides a built-in print() function that can be useful for simple debugging purposes. The built-in print() function writes to standard output. You can redefine the print() function (or add your own function, e.g. debug() or log()) that redirects the text to somewhere else. The following code shows a custom print() that adds text to a QPlainTextEdit.
所以这里是建议重新定义print()
:
QScriptValue QtPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}
QScriptValue calleeData = context->callee().data();
QPlainTextEdit *edit = qobject_cast<QPlainTextEdit*>(calleeData.toQObject());
edit->appendPlainText(result);
return engine->undefinedValue();
}
起初我怀疑return engine->undefinedValue();
是否需要返回一个“Undefined Value”,看起来像参数*的作用engine
就是返回这个void值。
所以这是我为更改函数所做的工作:
QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}
/*
QScriptValue calleeData = context->callee().data();
QPlainTextEdit *edit = qobject_cast<QPlainTextEdit*>(calleeData.toQObject());
edit->appendPlainText(result);
return engine->undefinedValue();
*/
return engine->toScriptValue(result); // ---> return the result directly
}
我认为这对我来说更合理:从脚本引擎返回一个评估的QScriptValue
,然后该值可以被转换为QString
用于输出。这绕过了动态类型转换的需要,这可能会变得困惑,特别是对于定制的 QObjects。
对于这两种打印函数,这里是对脚本引擎的说明:
QScriptEngine *engine = new QScriptEngine(this);
QTextEdit *input = new QTextEdit(this);
QTextEdit *output = new QTextEdit(this);
// Use documented print function :
QScriptValue fun = engine->newFunction(QtPrintFunction);
// Use my revised print function :
// QScriptValue fun = engine->newFunction(myPrintFunction);
fun.setData(engine->newQObject(output));
engine->globalObject().setProperty("print", fun);
评估和输出:
QString command = input->toPlainText();
QScriptValue result = engine->evaluate(command);
output->append(result.toString());
(需要Qt版本> 4)
test.pro
QT += core gui widgets script
TARGET = Test
TEMPLATE = app
SOURCES += main.cpp\
console.cpp
HEADERS += console.h
main.cpp
#include <QApplication>
#include "console.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Console w;
w.show();
return app.exec();
}
console.h
#ifndef CONSOLE_H
#define CONSOLE_H
#include <QWidget>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QScriptEngine>
class Console : public QWidget
{
Q_OBJECT
public:
Console();
~Console();
public slots:
void runScript();
private:
QScriptEngine *engine;
QVBoxLayout *layout;
QPushButton *run;
QTextEdit *input, *output;
};
QScriptValue QtPrintFunction(QScriptContext *context, QScriptEngine *engine);
QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine);
#endif // CONSOLE_H
控制台.cpp
#include "console.h"
Console::Console()
{
engine = new QScriptEngine(this);
layout = new QVBoxLayout(this);
run = new QPushButton("Run",this);
input = new QTextEdit(this);
output = new QTextEdit(this);
layout->addWidget(input);
layout->addWidget(run);
layout->addWidget(output);
//QScriptValue fun = engine->newFunction(QtPrintFunction);
QScriptValue fun = engine->newFunction(myPrintFunction);
fun.setData(engine->newQObject(output));
engine->globalObject().setProperty("print", fun);
connect(run, SIGNAL(clicked()), this, SLOT(runScript()));
}
void Console::runScript()
{
QString command = input->toPlainText();
QScriptValue result = engine->evaluate(command);
output->append(result.toString());
}
QScriptValue QtPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}
QScriptValue calleeData = context->callee().data();
QTextEdit *edit = qobject_cast<QTextEdit*>(calleeData.toQObject());
edit->append(result);
return engine->undefinedValue();
}
QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}
return engine->toScriptValue(result);
}
Console::~Console()
{
}
输入 1:
print(123);
输出(Qt 文档 QtPrintFunction()
):
123
undefined
输出(我的版本 myPrintFunction()
):
123
输入 2:
for (i = 0; i < 3; i++)
print(i);
输出(Qt 文档 QtPrintFunction()
):
0
1
2
undefined
输出(myPrintFunction()
):
2
输入 3:
print("Stack");
print("Overflow");
输出(Qt 文档 QtPrintFunction()
):
Stack
Overflow
undefined
输出(我的版本 myPrintFunction()
):
Overflow
虽然 myPrintFunction
一开始似乎工作正常,但当脚本中调用了两个以上的 print
时它就不起作用了,其中只有最后一个 print
将被执行。
最佳答案
返回 undefinedValue()
并不是必须的,但是当你这样做的时候,就等于什么都不返回。或者本质上,就像您将函数声明为 void print(...)
一样,可以这么说。
这就是 QtPrintFunction
所做的——它返回“无”。但它确实有一个副作用,即无论何时调用它,都会将其参数附加到内部数据对象。这就是为什么您在 output
对象中获取所有传递给 print
的值。
现在,当您调用 engine->evaluate()
时,它会返回最后 计算表达式的值。因此,使用 myPrintFunction
,您只能获得 last 值。
因此,如果您要输入以下内容:
print("Stack");
print("Overflow");
"garbage";
您只会返回垃圾
(双关语),因为这是最后计算的表达式。
但是,如果你要输入这个:
print("Stack") + '\n' +
print("Overflow");
如您所料,您将获得这两个值。
此外,如果您输入:
result = "";
for (i = 0; i < 3; i++)
result += print(i) + '\n';
你也会得到你所期望的。
希望这能解释为什么你的函数会这样运行。
但是,我认为这不是您要实现的目标。所以...继续前进。
您可以做的一件事是按如下方式定义myPrintFunction
:
QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
static QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}
result.append('\n');
return engine->toScriptValue(result);
}
这将按照您预期的方式“工作”。唯一的问题是您无法清除result
的值。如果这对您有用,那就是了。
有一个更好的方法可以做到这一点,这可能是定义一个类,例如:
class QTrace: public QObject
{
...
void clear();
void append(const QString& value);
const QString& get();
}
并将该类的对象传递给 fun.setData(engine->newQObject(trace))
并将您的函数定义为:
QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}
result.append('\n');
QScriptValue calleeData = context->callee().data();
QTrace *trace = qobject_cast<QTrace*>(calleeData.toQObject());
trace->append(result);
return engine->undefinedValue();
}
最后,您可以将 runScript
函数更改为如下内容:
trace->clear();
QScriptValue result = engine->evaluate(command);
if(result.isError())
output->append(result.toString());
else
output->append(trace->get());
或者可能还有其他方法,但希望能帮助您朝着正确的方向前进。
关于javascript - 为 QScriptEngine 重新定义 "Undefined Value"函数时返回 "print()"有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27613481/
我正在尝试使用 flot 绘制 SQL 数据库中的数据图表,这是使用 php 收集的,然后使用 json 编码的。 目前看起来像: [{"month":"February","data":482},
我有一个来自 php 行的 json 结果,类似于 ["value"]["value"] 我尝试使用内爆函数,但得到的结果是“value”“value” |id_kategori|created_at
脚本 1 将记录 two 但浏览器仍会将 select 元素呈现为 One。该表单还将提交值 one。 脚本 2 将记录、呈现和提交 两个。我希望它们是同义词并做同样的事情。请解释它们为何不同,以及我
我的python字典结构是这样的: ips[host][ip] 每行 ips[host][ip] 看起来像这样: [host, ip, network, mask, broadcast, mac, g
在 C# 中 我正在关注的一本书对设置和获取属性提出了这样的建议: double pri_test; public double Test { get { return pri_test; }
您可能熟悉 enum 位掩码方案,例如: enum Flags { FLAG1 = 0x1, FLAG2 = 0x2, FLAG3 = 0x4, FLAG4 = 0x8
在一些地方我看到了(String)value。在一些地方value.toString() 这两者有什么区别,在什么情况下我需要使用哪一个。 new Long(value) 和 (Long)value
有没有什么时候 var result = !value ? null : value[0]; 不会等同于 var result = value ? value[0] : null; 最佳答案 在此处将
我正在使用扫描仪检测设备。目前,我的条形码的值为 2345345 A1。因此,当我扫描到记事本或文本编辑器时,输出将类似于 2345345 A1,这是正确的条形码值。 问题是: 当我第一次将条形码扫描
我正在读取 C# 中的资源文件并将其转换为 JSON 字符串格式。现在我想将该 JSON 字符串的值转换为键。 例子, [ { "key": "CreateAccount", "text":
我有以下问题: 我有一个数据框,最多可能有 600 万行左右。此数据框中的一列包含某些 ID。 ID NaN NaN D1 D1 D1 NaN D1 D1 NaN NaN NaN NaN D2 NaN
import java.util.*; import java.lang.*; class Main { public static void main (String[] args) thr
我目前正在开发我的应用程序,使其设计基于 Holo 主题。在全局范围内我想做的是工作,但我对文件夹 values、values-v11 和 values-v14. 所以我知道: values 的目标是
我遇到了一个非常奇怪的问题。 我的公司为我们的各种 Assets 使用集中式用户注册网络服务。我们一般通过HttpURLConnection使用请求方法GET向Web服务发送请求,通过qs设置参数。这
查询: UPDATE nominees SET votes = ( SELECT votes FROM nominees WHERE ID =1 ) +1 错误: You can't specify
如果我运行一段代码: obj = {}; obj['number'] = 1; obj['expressionS'] = 'Sin(0.5 * c1)'; obj['c
我正在为我的应用创建一个带有 Twitter 帐户的登录页面。当我构建我的项目时会发生上述错误。 values/strings.xml @dimen/abc_text_size_medium
我在搜索引擎中使用以下 View : CREATE VIEW msr_joined_view AS SELECT table1.id AS msr_id, table1.msr_number, tab
为什么验证会返回此错误。如何解决? ul#navigation li#navigation-3 a.current Value Error : background-position Too
我有一个数据名如下 import pandas as pd d = { 'Name' : ['James', 'John', 'Peter', 'Thomas', 'Jacob', 'Andr
我是一名优秀的程序员,十分优秀!