Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7701字,纯文字阅读大概需要12分钟。
内容图文
话接上文。笔者为了方便使用Lua,自己编写了一个Lua的类。主要代码如下:
QLua.h
1 #ifndef QLUA_H 2 #define QLUA_H 3 4// own 5 #include "include/lua.hpp" 6 7// qt 8 #include <QObject> 9 #include <QFile> 10 #include <QDebug> 1112 #include <QWidget> 13 #include <QLineEdit> 14 #include <QPushButton> 15 #include <QMessageBox> 1617class QLua : public QObject 18{ 19 Q_OBJECT 20public: 21 QLua(QObject *parent = 0); 22 ~QLua(); 2324// lua25void init(); 26void close(); 2728void pushFunction(QString funcName, lua_CFunction func); 2930void beginModule(QString); 31void addType(QString, lua_CFunction deleteFunc); 32void moduleTypeFunction(QString, lua_CFunction); 33void endModule(); 3435void run(QString); 36signals: 3738public slots: 3940private: 41 lua_State *luaState; 4243bool isStartModule; 44}; 4546#endif// QLUA_H
QLua.cpp
1 #include "qlua.h" 2 3 QLua::QLua(QObject *parent) : 4 QObject(parent) 5 , luaState(NULL) 6 , isStartModule(false) 7{ 8 init(); 9} 1011 QLua::~QLua() 12{ 13 close(); 14} 1516void QLua::init() 17{ 18 luaState = luaL_newstate(); 19 luaL_openlibs(luaState); 20} 2122void QLua::close() 23{ 24if(luaState != NULL) 25 { 26 lua_close(luaState); 27 luaState = NULL; 28 } 29} 3031void QLua::pushFunction(QString funcName, lua_CFunction func) 32{ 33if (funcName.isEmpty()) return; 34if (func == NULL) return; 3536 lua_pushcfunction(luaState, func); 37 lua_setglobal(luaState, funcName.toLocal8Bit().data()); 38} 3940void QLua::beginModule(QString name) 41{ 42if(luaState == NULL) return; 4344if (isStartModule == false) 45 { 46 tolua_open(luaState); 47 tolua_module(luaState, NULL, 0); 48 isStartModule = true; 49 } 5051constchar *str = name.isEmpty()? NULL : name.toLocal8Bit().data(); 52 tolua_beginmodule(luaState, str); 53} 5455void QLua::addType(QString name, lua_CFunction deleteFunc) 56{ 57if (luaState == NULL) return; 58if (name.isEmpty()) return; 59if (deleteFunc == NULL) return; 6061 tolua_usertype(luaState, name.toLocal8Bit().data()); 62constchar *str = name.toLocal8Bit().data(); 63 tolua_cclass(luaState, str, str, "", deleteFunc); 64 beginModule(name); 65} 6667void QLua::moduleTypeFunction(QString name, lua_CFunction func) 68{ 69if(luaState == NULL) return ; 70if (name.isEmpty()) return; 7172constchar *str = name.toLocal8Bit().data(); 73 tolua_function(luaState, str, func); 74} 7576void QLua::endModule() 77{ 78 tolua_endmodule(luaState); 79} 8081void QLua::run(QString str) 82{ 83 luaL_loadbuffer(luaState, str.toLocal8Bit().data(), str.length(), "line"); 84 lua_pcall(luaState, 0, 0, 0); 85 }
QLua类可以方便的实现一些简单的Lua操作,如初始化,关闭,运行Lua代码,绑定函数等。
笔者目前想做到的是能在Lua代码中自有的生成Qt对象,然后能连接Qt原生对象的信号与槽。那么如何实现呢?
Qt中连接信号与槽的函数是QObject::connect(QObject * a, SIGNAL(), QObject * b, SLOT())。首先,我们要弄清楚SIGNAL和SLOT到底是什么。
从connect的参数列表中,我们可以很清晰的看到SIGNAL和SLOT的结果都是char*类型的字符串。我们可以直接在SIGNAL上点右键,转到SIGNAL的定义。或者做个简单的实验。测试如下Qt代码:
qDebug() << QString::fromLocal8Bit(SIGNAL(clicked()));
qDebug() << QString::fromLocal8Bit(SLOT(close()));
得到的结果很有意思:
简单总结就是我们只要传入函数名的字符串,加上前缀即可。SIGNAL的前缀是2,SLOT的前缀是1。
这样我们就可以实现在Lua中的connect函数了。仍在使用C++编写,然后绑定到Lua里。如下:
1 static int connect(lua_State* state) 2{ 3 QObject * a = (QObject*)tolua_tousertype(state, 1, 0); 4constchar * signal = tolua_tostring(state, 2, 0); 5 QObject * b = (QObject*)tolua_tousertype(state, 3, 0); 6constchar * slot = tolua_tostring(state, 4, 0); 7 8 QObject::connect(a, QString("2%0").arg(signal).toLocal8Bit().data(), 9 b, QString("1%0").arg(slot).toLocal8Bit().data()); 10 }
绑定时可以使用上面的QLua类:
完整main.cpp代码如下:
#include "include/lua.hpp" #include "qlua.h" #include <QWidget> #include <QApplication> #include <QFile> #include <QDebug> staticint test(lua_State* state) { QPushButton* a = (QPushButton*)tolua_tousertype(state, 1, 0); if(a) a->show(); } staticint connect(lua_State* state) { QObject * a = (QObject*)tolua_tousertype(state, 1, 0); constchar * signal = tolua_tostring(state, 2, 0); QObject * b = (QObject*)tolua_tousertype(state, 3, 0); constchar * slot = tolua_tostring(state, 4, 0); QObject::connect(a, QString("2%0").arg(signal).toLocal8Bit().data(), b, QString("1%0").arg(slot).toLocal8Bit().data()); } staticint tolua_new_QWidget(lua_State* state) { QWidget* widget = new QWidget(); tolua_pushusertype(state, widget, "QWidget"); return1; } staticint tolua_delete_QWidget(lua_State* state) { qDebug() << "delete Start"; QWidget* widget = (QWidget* )tolua_tousertype(state, 1, 0); if(NULL != widget) { qDebug() << "delete~"; widget->close(); delete widget; } return1; } staticint tolua_Show_QWidget(lua_State* state) { QWidget* widget = (QWidget* )tolua_tousertype(state, 1, 0); if(widget != NULL) { widget->show(); } return1; } staticint tolua_new_QPushButton(lua_State* state) { QPushButton* button = new QPushButton(); tolua_pushusertype(state, button, "QPushButton"); return1; } staticint tolua_delete_QPushButton(lua_State* state) { QPushButton* button = (QPushButton* )tolua_tousertype(state, 1, 0); if(NULL != button) { button->close(); delete button; } return1; } staticint tolua_Show_QPushButton(lua_State* state) { QPushButton* button = (QPushButton* )tolua_tousertype(state, 1, 0); if(button != NULL) { button->show(); } return1; } staticint tolua_setText_QPushButton(lua_State* state) { QPushButton* button = (QPushButton* )tolua_tousertype(state, 1, 0); constchar * text = tolua_tostring(state, 2, 0); if(button != NULL) { button->setText(QString::fromLocal8Bit(text)); } return1; } staticint tolua_Resize_QWidget(lua_State* state) { QWidget* widget = (QWidget* )tolua_tousertype(state, 1, 0); double a = tolua_tonumber(state, 2, 0); double b = tolua_tonumber(state, 3, 0); if(widget) { widget->resize((int)a, (int)b); } return1; } staticint QApplication_instance(lua_State* state) { tolua_pushusertype(state, QApplication::instance(), "QApplication"); return1; } staticint QApplication_quit(lua_State* state) { QApplication * app = (QApplication *)tolua_tousertype(state, 1, 0); if(app) app->quit(); return1; } staticint QApplication_delete(lua_State*) { return1; } int main(int argc, char * argv[]) { Q_INIT_RESOURCE(resources); QApplication a(argc, argv); QLua lua; lua.beginModule(""); lua.addType("QWidget", tolua_delete_QWidget); lua.moduleTypeFunction("new", tolua_new_QWidget); lua.moduleTypeFunction("show", tolua_Show_QWidget); lua.moduleTypeFunction("resize", tolua_Resize_QWidget); lua.endModule(); lua.addType("QPushButton", tolua_delete_QPushButton); lua.moduleTypeFunction("new", tolua_new_QPushButton); lua.moduleTypeFunction("show", tolua_Show_QPushButton); lua.moduleTypeFunction("setText", tolua_setText_QPushButton); lua.endModule(); lua.addType("QApplication", QApplication_delete); lua.moduleTypeFunction("instance", QApplication_instance); lua.moduleTypeFunction("quit", QApplication_quit); lua.endModule(); lua.endModule(); lua.pushFunction("test", test); lua.pushFunction("connect", connect); // 读取资源文件 QFile file("://test.lua"); file.open(QIODevice::ReadOnly | QIODevice::Text); QTextStream in(&file); in.setCodec("UTF-8"); // 执行 lua.run(in.readAll()); return a.exec(); }
test.lua代码如下:
widget = QWidget:new() widget:show() button = QPushButton:new() button:setText("China") button:show() connect(button, "clicked()", widget, "close()") connect(button, "clicked()", button, "close()") print("run over")
程序运行结果如下:
点击China按钮,button和widget的窗口都会关闭。
至此,已经实现了连接 Qt 对象的信号与槽。
如果继续做下去,完全可以实现在Lua脚本中使用Qt的类和对象,写出Lua的Gui程序。
附完整代码工程文件:http://pan.baidu.com/s/1ntmFdjj
附个偶的博客地址:http://www.cnblogs.com/IT-BOY/
原文:http://www.cnblogs.com/IT-BOY/p/3573618.html
内容总结
以上是互联网集市为您收集整理的Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象全部内容,希望文章能够帮你解决Win32下 Qt与Lua交互使用(三):在Lua脚本中connect Qt 对象所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。