【发布时间】:2014-12-23 02:59:16
【问题描述】:
[背景]
QScriptEngine 的默认print() 函数将结果打印到 Qt Creator IDE 的终端以进行调试。因此,如果我们要自己制作 ECMA 脚本解释器,则必须将输出重定向到我们的文本编辑器。
自 Qt 4.3 以来,文档"Making Applications Scriptable" 的这一部分保持不变。
Qt Script 提供了一个内置的 print() 函数,可以用于 简单的调试目的。内置 print() 函数写入 标准输出。您可以重新定义 print() 函数(或添加您的 自己的功能,例如debug() 或 log()) 将文本重定向到 别的地方。以下代码显示了一个自定义 print(),它添加了 文本到 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();是否需要返回一个“未定义的值”,看来*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
console.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
未定义
输出 (myPrintFunction()):
2
输入 3:
print("Stack");
print("Overflow");
输出(Qt 文档QtPrintFunction()):
堆栈
溢出
未定义
输出(我的版本myPrintFunction()):
溢出
[问题]
虽然myPrintFunction 一开始似乎可以正常工作,但是当脚本中调用了两个以上的print 时,它就不起作用了,只有最后一个print 会被执行。
It seems the returning of an "Undefined Value" is NECESSARY for the print function. But why???
【问题讨论】:
-
作为括号中的旁注,QtScripts 已经“完成(甚至可能已经过时?)一段时间了。这是我在 2013 年毕尔巴鄂 QtCS 之后的想法。
-
但不是 Javascript。我认为
QScriptEngine可以同时阅读它们,所以基本上我的目标是专注于 Javascirpt。或者您可能建议我删除qtscript标签? -
我只是想写一下,您将来可能想放弃使用
QtScript。 (顺便说一句,这是语法错误:QScriptEngin engine;) -
它是在当时创建的,因为允许简单的脚本选项很有趣,例如我们在游戏开发者的游戏创建者 IDE 中使用,但后来 Qt 项目认为新的 v4 引擎是未来。
-
如何“输出”使用
myPrintFunction打印的内容?输出出现在哪里?请在您的问题中说明这一点
标签: javascript c++ qt interpreter read-eval-print-loop