TinUI较复杂面板布局演示
TinUI面板布局
在TinUI v6版本中,添加了面板布局的支持,文章TinUI v6 面板布局有详细介绍,并且给出了TinUI储存库里的两个应用作为示例,其中,TinUI画廊结构很简单,只有三个控件;TinUIXml编辑器结构复杂一点,但是本质上和画廊的布局一样,只不过从画廊的左侧纵向布局变成了顶部工具栏的水平布局,并且缺乏详细的布局思路解释。本文将以一个较复杂的界面为例子,详细解释TinUI中面板布局的思路。
例子就拿我模仿FreeTex写的AutoTex为例(这个项目本身的目的见介绍文档)。
界面大概
以下是界面:

首先是顶部的工具栏,然后是latex结果展示文本框,底部是信息栏外加一个公式包裹选项框,整体宽度固定为400单位,但是高度为仅文本框填充。
右侧两个区域,上方为图片展示,下方为公式预览。这两个区域上下平分窗口剩余的空间。
之所以让控件位置、尺寸可变,是因为作为一个公式识别应用,无论是图片展示还是公式预览,没有理由固定区域尺寸,而左侧的文本框已经有了滚动条,尺寸是否可变意义不大,不过既然右侧有需求,那么左侧仅让文本框高度变化即可。
本界面中,所有元素与边框间隔为5个单位。
布局思路
开始就要记住,TinUI的面板布局是半动态布局,需要额外指定固定尺寸。
其实从上面的简短分析,我们已经将界面分为左右两部分。根据TinUI面板布局的设计,以一个ExpandPanel作为根面板,接下来就是添加一个水平面板。
def updateExpand(e):rp.update_layout(0, 0, e.width, e.height)rp=ExpandPanel(ui, padding=(5, 5, 5, 5))
ui.bind("<Configure>", updateExpand)
hp=HorizonPanel(ui, spacing=5)
rp.set_child(hp)

也显然,两边都是一个纵向面板。不过先来看左边。
要想实现那样的界面,肯定需要将水平部分分割为三个部分,而由于文本框独占一行,所有直接使用ExpandPanel,上下两行使用HorizonPanel。
vp=VerticalPanel(ui)
hp.add_child(vp,400)top=HorizonPanel(ui, spacing=5, padding=(0, 5, 0, 5))
vp.add_child(top,50)
btn=ui.add_button2((0,0), text='复制', command=copy, anchor='w')[-1]
top.add_child(btn,50)
btn=ui.add_button2((0,0), text='复制MathML(Word)', command=copy_mathml, anchor='w')[-1]
top.add_child(btn,230)
onoff,onoffid=ui.add_onoff((0,0), bd=30, command=set_reverse, anchor='w')[-2:]
top.add_child(onoffid,40)
para=ui.add_paragraph((0,0), text='原图', anchor='w')
top.add_child(para,120)ep=ExpandPanel(ui)
vp.add_child(ep,weight=1)
#...
ep.set_child(textid)bop=HorizonPanel(ui, spacing=5, padding=(0, 5, 0, 5))
vp.add_child(bop,40)
info=ui.add_paragraph((0,0), text='模型加载中...', anchor='w')
bop.add_child(info,200)
combobutton=ui.add_combobox((0,0), width=150, height=120, text='公式包裹(默认无)', content=('无包裹','$$...$$','\\begin{equation}...'), command=latex_add, anchor='w')[-1]
bop.add_child(combobutton,120)

由于外层的
HorizonPanel限制了左侧纵向面板的宽度,所以里面再使用ExpandPanel,将只会在纵向上填充空间。
此外,也由于宽度固定,上方按钮和开关直接的间隔直接使用维护多余空间实现(230显然大于按钮所需单位),下方信息文本和选择框的间隔也如此实现。
右侧也简单,两个区域纵向平分剩余空间,显然就是一个VerticalPanel下夹两个权重相同的ExpandPanel。问题来了,怎么让它们水平填充剩余空间?需要给VerticalPanel外再套一层ExpandPanel吗?不需要,在最外层水平面添加右侧纵向面板时,指定权重为1(大于0就行)就可以了。
TinUI面板布局设计上就是这样的,只维护空间,任何空间都是可以填充的,只不过不同面板将空间反馈给控件的形式不一样。ExpandPanel会告诉控件尝试填充自己维护的整个控件,而排列面板只会让控件在维护的空间中进行对齐。
这就很简单了:
vp2=VerticalPanel(ui,spacing=5)
hp.add_child(vp2,weight=1)
ep2=ExpandPanel(ui)
vp2.add_child(ep2,weight=1)
ep3=ExpandPanel(ui)
vp2.add_child(ep3,weight=1)

窗口缩放演示
布局结构就很清晰,以放大还原为例:

