关于XToolBox
从零开始
XToolBox 是在开发一个工具的时候,偶然得到的。
为了满足在Ubuntu和Windwos上都能够使用需求,采用了跨平台的Qt做为框架来开发。代码只需要一份,就能编译出两个系统上的可执行文件。
开发时,业务逻辑并不十分明确,用户会有一些个性化的定制要求,于是就引入了lua脚本语言来做业务逻辑定制。根据业务逻辑的不同,界面元素也会有所不同,因此在脚本中需要能够定制界面元素。这里采用luabind将Qt的界面类绑定到了lua中,这样便能在lua脚本中定制界面了。
在那个工具开发完工后,突然想到,如果我把界面和逻辑全用lua实现会如何,宿主程序只提供一个框架,并不实现任何业务逻辑。在这样的思路下,XToolBox诞生了。
信号和槽
信号和槽是Qt中最好用的一个特性,通过信号和槽能够关联两个不同的对象。最典型的场景就是将一段过程处理代码绑定到按钮的点击信号上,当点击事件发生时,触发相应的代码。在Qt中,用connect将信号和槽关联起来,在XToolBox中,信号是一个属性,槽就是普通的lua函数(closure),连接信号和槽看起来是下面这样的。
btn.clicked = function(arg) -- do something after button clicked end
这里的槽看起来没有绑定到某一个特定对象上,和Qt中有点不太一样。因为在lua中,一个函数实际上是一个闭包,在函数中用到的对象会自动保存在函数的上下文中(upvalue),所以我们在绑定时,不用刻意去指定槽的对象,直接在函数中引用即可。实际上槽函数是绑定到了整个lua状态机上,在lua中所有可见的对象都能在槽中使用。
界面元素的布局
Qt中的界面元素可以通过QxxxLayout进行布局,在布局中的元素会自动调整位置,并在界面调整时保持相对关系。在Qt上可以通过界面设计器或者代码来设置布局。在XToolBox中可以用Qt风格的代码来设置布局,看起来是这样的
frame = QFrame() text1 = QTextEdit() text2 = QTextEdit() button = QPushButton("&Copy") layout = QVBoxLayout() layout:addWidget(text1) layout:addWidget(text2) layout:addWidget(button) frame.layout = layout button.clicked = function() text2.plainText = text1.plainText end mdiArea:addSubWindow(frame):show()
不过更方便的是用XToolBox特有的风格来进行布局,像下面这样
frame = QFrame() text1 = QTextEdit() text2 = QTextEdit() button = QPushButton("&Copy") frame.layout = QVBoxLayout{ text1, text2, button, stretch = "1,0,0" } button.clicked = function() text2.plainText = text1.plainText end mdiArea:addSubWindow(frame):show()
这样的风格设置布局看起来更像是在写一个配置文件,更加的方便和直观。
上面的代码执行后的结果如下: