引言
在GUI制作中,有时会用到信息小标签,用来显示个数多、字数少、内容相关的文字信息。
这种小标签相当于一个个小卡片,用途很广泛,如引用各类文献的摘要、对一个功能的多点说明等等,可以提高程序的使用顺手度。该功能一般使用Label组件或LabelFrame组件的pack布局,但是pack布局在组件较多时,往往会导致界面分类不科学、占用界面面积大、界面外形古板。那么我们可以对这种办法进行升级,让卡片集中在一个Frame框架里,同时这些小标签还可以被拖动、相互覆盖。
内容显示
为了保持界面美观,每个小标签使用LabelFrame显示标题,使用ScrolledText显示内容。
拖动
部位
为了便于使用者操作,当鼠标拖动LabelFrame时,卡片可以移动,但是拖动文本框时,卡片不会响应。
代码实现
以下是完成拖动的逻辑代码:
def mousedown(event):
widget=event.widget
widget.startx=event.x
widget.starty=event.y
def drag(event):
widget=event.widget
try:
if isinstance(widget,tk.Wm):
widget.geometry("+%d+%d"%(widget.winfo_x()+(event.x-widget.startx),
widget.winfo_y()+(event.y-widget.starty)))
else:
widget.place(x=widget.winfo_x()+(event.x-widget.startx),
y=widget.winfo_y()+(event.y-widget.starty))
except AttributeError:
raise ValueError("The widget %s is not draggable"%widget)
def draggable(tkwidget):
"""调用draggable(tkwidget) 使tkwidget可拖动。
tkwidget为一个控件(Widget)或一个窗口(Wm)。"""
tkwidget.bind("<Button-1>",mousedown,add='+')
tkwidget.bind("<B1-Motion>",drag,add='+')
覆盖
我们总不可能让标签都按照创建时的层级呈现给使用者吧?卡片在被点击时会出现在最上层,即增加界面的交互性和动态感,又有利于使用者查看。
在tkinter中,每一个组件都有一个 tkraise 函数,我们只用在鼠标点击时绑定这个函数即可。
很简单的完整代码
class CardsFrame(Frame):
"""可以显示多个卡片的容器"""
def add_card(self,title,con,x=10,y=10,width=100,height=200,fg='black',bg='white'):
pa=LabelFrame(self,width=width,height=height,text=title,relief='groove',font="-family {Microsoft YaHei UI} -size 9",fg=fg)
mi=scrolledtext.ScrolledText(pa,font="-family {Microsoft YaHei UI} -size 11",fg=fg,bg=bg,cursor='arrow')
mi.insert('end',con)
mi.vbar['width']=9#减少滚动条的面积
mi['state']='disable'#禁止编辑
mi.pack(fill='both',expand=True)
pa.place(x=x,y=y,width=width,height=height)
pa.bind('<Button-1>',lambda event:pa.tkraise())#绑定覆盖
draggable(pa)#绑定滚动
draggable的代码在上文已经给出
效果如下:
Tin知识库
结语
通过对GUI界面的完善,同样可以让tkinter制作出高颜值的界面窗口。
☀tkinter创新☀