以traits为基础,以 MVC 为设计思想。
MVC:Modle-View-Controller
官方文档
from traits.api import HasTraits, Str, Int
class ModelManager(HasTraits):
model_name = Str
category = Str
model_file = Str
model_number = Int
if __name__ == "__main__":
model = ModelManager()
model.configure_traits()
文字标签根据trait属性名自动生成:
后台界面库 | 程序启动时选择界面库参数 |
---|---|
qt4 | -toolkit qt4 |
Wx | –toolkit wx |
MVC类别 | MVC说明 |
---|---|
Model | HasTraits的派生类用Trait保存数据,相当于模型 |
View | 没有指定界面显示方式时,Traits自动建立默认界面 |
Controller | 起到视图和模型之间的组织作用,控制程序的流程 |
View(title,width,height,resizable…)
属性 | 说明 |
---|---|
title | 窗口标题栏 |
Width | 窗口宽度 |
Height | 窗口高度 |
resizable | 窗口大小可变,默认为True |
Item(id,name,label…)
属性 | 说明 |
---|---|
id | item的唯一id |
name | trait属性的名称 |
label | 静态文本,用于显示编辑器的标签 |
tooltip | 编辑器的提示文本 |
from traits.api import HasTraits, Str, Int
from traitsui.api import View, Item
class ModelManager(HasTraits):
model_name = Str
category = Str
model_file = Str
model_number = Int
view = View(
Item('model_name', label=u"模型名称"),
Item('model_file', label=u"文件名"),
Item('category', label=u"模型类型"),
Item('model_number', label=u"模型数量"),
title=u"模型资料", width=220, resizable=True)
if __name__ == "__main__":
model = ModelManager()
model.configure_traits()
属性 | 说明 |
---|---|
orientation | 编辑器的排列方向 |
layout | 布局方式normal、flow、split、tabbed |
show_labels | 是否显示编辑器的标签 |
columns | 布局的列数,范围为(1,50) |
from traits.api import HasTraits, Str, Int
from traitsui.api import View, Item, Group
from traitsui.menu import ModalButtons
class ModelManager(HasTraits):
model_name = Str
category = Str
model_file = Str
model_number = Int
vertices = Int
if __name__ == "__main__":
view1 = View(
Group(
Item('model_name', label=u"模型名称"),
Item('model_file', label=u"文件名"),
Item('category', label=u"模型类型"),
label=u'模型信息',
show_border=True),
Group(
Item('model_number', label=u"模型数量"),
Item('vertices', label=u"顶点数量"),
label=u'统计数据',
show_border=True),
)
model = ModelManager()
model.configure_traits(view=view1)
如果想要不分标签页显示,可以在外面再嵌套一个Group。
from traits.api import HasTraits, Str, Int
from traitsui.api import View, Item, Group
from traitsui.menu import ModalButtons
class ModelManager(HasTraits):
model_name = Str
category = Str
model_file = Str
model_number = Int
vertices = Int
if __name__ == "__main__":
view1 = View(
Group(
Group(
Item('model_name', label=u"模型名称"),
Item('model_file', label=u"文件名"),
Item('category', label=u"模型类型"),
label=u'模型信息',
show_border=True),
Group(
Item('model_number', label=u"模型数量"),
Item('vertices', label=u"顶点数量"),
label=u'统计数据',
show_border=True),
)
)
model = ModelManager()
model.configure_traits(view=view1)
在外层Group添加orientation = 'horizontal'
派生类 | 说明 |
---|---|
HGroup | 内容水平排列Group(orientation=‘horizontal’) |
HFlow | 内容水平排列,超过水平宽度时,自动换行,隐藏标签文字。Group(orientation=‘horizontal’,layout=‘flow’,show_labels=False) |
HSplit | 内容水平分隔,中间插入分隔条Group(orientation=‘horizontal’,layout=‘flow’) |
Tabbed | 内容分标签页显示Group(orientation=‘horizontal’,layout=‘tabber’ ) |
VGroup | 内容垂直排列Group(orientation=‘vertical’) |
VFlow | 内容垂直排列,超过垂直高度时,自动换列,隐藏标签文字Group(orientation=‘vertical’,layout=‘flow’,show _labels=False) |
VFold | 内容垂直排列,可折叠Group(orientation=‘vertical’,layout=‘fold’,show _labels=False) |
VGrid | 按照多列网格进行垂直排列,columns属性决定网格的列数Group(orientation=‘vertical’, columns=2) |
VSplit | 内容垂直排列,中间插入分隔条Group(orientation=‘vertical’,layout=‘split’) |
from traitsui.api import HSplit, VGroup, View, Item
from traits.api import HasTraits, Str, Int
class ModelManager(HasTraits):
model_name = Str
category = Str
model_file = Str
model_number = Int
vertices = Int
if __name__ == "__main__":
view1 = View(
HSplit(
VGroup(
Item('model_name', label=u"模型名称"),
Item('model_file', label=u"文件名"),
Item('category', label=u"模型类型"),
label=u'模型信息',
),
VGroup(
Item('model_number', label=u"模型数量"),
Item('vertices', label=u"顶点数量"),
label=u'统计数据',
)
)
)
model = ModelManager()
model.configure_traits(view=view1)
from traits.api import HasTraits, Str, Int
from traitsui.api import View, Item, Group
g1 = [Item('model_name', label="模型名称"),
Item('category', label="模型类型")]
g2 = [Item('model_number', label="模型数量"),
Item('vertices', label="顶点数量")]
class ModelManager(HasTraits):
model_name = Str
category = Str
model_file = Str
model_number = Int
vertices = Int
traits_view = View(
Group(*g1, label='模型信息', show_border=True),
Group(*g2, label='统计数据', show_border=True),
title="内部试图")
global_view = View(
Group(*g1, label='模型信息', show_border=True),
Group(*g2, label='统计数据', show_border=True),
title="外部试图"
)
if __name__ == "__main__":
model = ModelManager()
# 内部试图
model.configure_traits()
model.configure_traits(view='traits_view')
# 外部视图
model.configure_traits(view=global_view)
通过kind属性设置View显示类型
显示类型 | 说明 |
---|---|
modal | 模态窗口,非即时更新 |
live | 非模态窗口,即时更新 |
livemodal | 模态窗口,即时更新 |
nonmodal | 非模态窗口,非即时更新 |
wizard | 向导窗口,模态窗口,即时更新 |
panel | 嵌入到其它窗口中的面板,即时更新,非模式 |
subpanel |
模态窗口:在此窗口关闭之前,其他窗口不能激活;
即时更新:修改控件内容,立即反应到模型数据上。
前四个采用窗口显示内容,后两个是嵌入窗口中的面板。
configure_traits | edit_traits() |
---|---|
界面显示后,进入消息循环 | 界面显示后,不进入消息循环。 |
主界面窗口或模态对话框 | 无模态窗口或对画框 |
标准命令按钮:
UndoButton、ApplyButton、RevertButton、OKButton、CancelButton、HelpButton
预定义命令按钮:
OKCancelButtons = [OKButton, CancelButton]
ModelButtons = [ApplyButton, RevertButton, OKButton, CancelButton, HelpButton]
LiveButtons = [UndoButton, RevertButton, OkButton, Cancel]
view1 = View(
Group(
Item('model_name', label=u"模型名称"),
Item('model_file', label=u"文件名"),
Item('category', label=u"模型类型"),
label=u'模型信息',
show_border=True),
Group(
Item('model_number', label=u"模型数量"),
Item('vertices', label=u"顶点数量"),
label=u'统计数据',
show_border=True),
kind='modal',
buttons=ModalButtons
)
model = ModelManager()
model.configure_traits(view=view1)
from traits.api import HasTraits, Str, Password
from traitsui.api import Item, Group, View
class TextEditor(HasTraits):
# 定义文本编辑器的变量
string_trait = Str("sample string")
password = Password
# 定义布局
text_str_group = Group(
Item('string_trait', style='simple', label='Simple'),
Item('_'),
Item('string_trait', style='custom', label='Custom'),
Item('_'),
Item('password', style='simple', label='password')
)
# 定义视图
traits_view = View(
text_str_group,
title='TextEditor',
buttons=['OK']
)
if __name__ == '__main__':
text = TextEditor()
text.configure_traits()
监听方法对比
作用 | Event属性 | Trait属性 |
---|---|---|
触发监听事件 | 对Event属性赋值 | 值被改变后 |
监听函数名 | _event_fired() | _trait_changed() |
from traits.api import HasTraits, Button, Int
from traitsui.api import View
class ButtonEditor(HasTraits):
# 定义一个Button trait:
my_button = Button('Click Me')
counter = Int
# 当按钮点击后,处理当按钮被点击后,触发的事件
def _my_button_fired(self):
self.counter += 1
# 创建视图
traits_view = View(
'my_button',
'counter',
title='ButtonEditor',
buttons=['OK'],
resizable=True)
if __name__ == '__main__':
button = ButtonEditor()
button.configure_traits()
from traits.api import HasTraits, Int, Range, Property, property_depends_on
from traitsui.api import View, Item, RangeEditor
class RangeDemo(HasTraits):
a = Range(1, 10)
b = Range(1, 10)
c = Property(Int)
view = View(
Item('a'),
Item('b'),
'_',
Item('c', editor=RangeEditor(low=1, high=20, mode='slider')),
Item('c'),
width=0.3
)
@property_depends_on('a,b', settable=True)
def _get_c(self):
print("computing")
return self.a + self.b
if __name__ == '__main__':
ran = RangeDemo()
ran.configure_traits()
对象 | 说明 |
---|---|
Action | 在Menu对象中,通过Action对象定义菜单中的每个选项 |
ActionGroup | 对菜单中的选项进行分组 |
Menu | 定义菜单栏中的一个菜单 |
MenuBar | 菜单栏对象,由多个Menu对象组成 |
ToolBar | 工具栏对象,它由多个Action对象组成,每个Action对 应工具条中的一个按钮 |
控件列表
对象 | 说明 |
---|---|
Array | 数组空间 |
Bool | 单选框、复选框 |
Button | 按钮 |
Code | 代码编辑器 |
Color | 颜色对话框 |
Dircetory | 目录控件 |
Enum | 枚举控件 |
File | 文件控件 |
Font | 字体选择控件 |
Html | Html网页控件 |
"""
演示TraitsUI的各种编辑器
"""
import os
from datetime import time
from traits.api import *
from traitsui.api import *
class EditorDemoItem(HasTraits):
"""界面右半部分,对于选中的某个Trait属性,使用4种样式创建属性编辑器"""
code = Code()
view = View(
Group(
# 使用simple编辑器,可尽量减少界面占用空间,width属性可指定编辑器宽度,负数表示强制设置宽度
Item("item", style="simple", label="simple", width=-300),
"_", # 下划线字符串表示创建分隔线
# 使用custom编辑器,可尽量呈现更多内容 #
# TODO: Trait,Enum,Range三个函数无法用于custom编辑器,要运行这三个函数需要将其注释
Item("item", style="custom", label="custom"),
"_",
# 使用text编辑器,只呈现文本内容
Item("item", style="text", label="text"),
"_",
# 使用readonly编辑器,呈现只读文本
Item("item", style="readonly", label="readonly"),
),
)
class EditorDemo(HasTraits):
"""创建主界面"""
codes = List(Str) # 创建List界面,用来展示各种Trait属性的字符串
selected_item = Instance(EditorDemoItem) # 初始化selected_item界面,用来存储被选项的编辑界面
selected_code = Str # 初始化selected_code变量,用来存储被选项名称
view = View(
# 使用HSplite水平分隔两个界面
HSplit(
# 界面左半部分,用来创建各种Trait属性的源程序列表
Item("codes", style="custom", show_label=False,
# 将editor属性设置为ListStrEditor(列表选择框控件),并更新selected_code变量
editor=ListStrEditor(editable=False, selected="selected_code")),
# 界面右半部分
Item("selected_item", style="custom", show_label=False),
),
resizable=True,
width=800,
height=400,
title=u"各种编辑器演示"
)
def _selected_code_changed(self):
"""当selected_code变量改变时触发,更新selected_item界面"""
item = EditorDemoItem(code=self.selected_code)
# 使用eval对selected_code字符串进行求值,并将值存储到item中
item.add_trait("item", eval(str(self.selected_code)))
self.selected_item = item
class Employee(HasTraits):
"""创建Employee类,该类为包含四个属性的界面"""
name = Unicode(label=u"姓名")
department = Unicode(label=u"部门")
salary = Int(label=u"薪水")
bonus = Int(label=u"奖金")
view = View("name", "department", "salary", "bonus")
if __name__ == '__main__':
employee = Employee()
demo_list = [u"低通", u"高通", u"带通", u"带阻"]
trait_defines = """
Array(dtype="int32", shape=(3,3)) #{1}fadsfa
Bool(True)
Button("Click me")
List(editor=CheckListEditor(values=demo_list))
Code("print('hello world')")
Color("red")
RGBColor("red")
Trait(*demo_list) #无法用于custom编辑器
Directory(os.getcwd())
Enum(*demo_list) #无法用于custom编辑器
File()
Font()
HTML('hello world')
List(Str, demo_list)
Range(1, 10, 5) #无法用于custom编辑器
List(editor=SetEditor(values=demo_list))
List(demo_list, editor=ListStrEditor())
Str("hello")
Password("hello")
Str("Hello", editor=TitleEditor())
Tuple(Color("red"), Range(1,4), Str("hello"))
Instance(EditorDemoItem, employee)
Instance(EditorDemoItem, employee, editor=ValueEditor())
Instance(time, time(), editor=TimeEditor())
"""
demo = EditorDemo()
# 一般写法
trait_list = []
for s in trait_defines.split('\n'): # 按行分割字符串
if s.split('#')[0].strip(): # 判断s中是否存在可执行函数
trait_list.append(s.split('#')[0]) # 去掉注释
demo.codes = trait_list
# 简洁写法
# demo.codes = [s.split("#")[0] for s in trait_defines.split("\n") if s.split('#')[0].strip()]
demo.configure_traits()