ui的设计,控件id的记录是一件比较繁琐的事情。

此外,赋值和读取数据也比较繁琐,非常不pythonic。

有没有神马办法优雅一点呢?life is short。

鉴于控件有name属性,通过dir(Entry_obj)得知,存放在一个_name的属性里面。于是就有了以下代码:

Entry(frame,name='your_id1').grid(row=x1,column=y1)
Entry(frame,name='your_id2').grid(row=x2,column=y2)
...
Entry(frame, name='your_idn').grid(row=xn,column=yn)

当然还有其他输入控件,此处略。

可以通过 frame.grid_slaves()得到其上面所有的控件。

然后可以通过 __class__来判断具体类型。可以在此基础上判断哪些控件是输入控件,如下:

for ctrl in frame.grid_slaves():
if ctrl.__class__.__name__ in ('Entry','Text',....):
return True
return False

  

此外,我们还需要一个映射表,来关联界面控件和我们的模型。

mapper={'model_attr1':ctrol_id1, 'model_attr2':ctrol_id2,...., 'model_attrn':ctrol_idn}

通过这个映射表,我们可以方便的进行表单数据的设置和读取,假设所有输入控件皆为Entry,于是就有了一下读取表单的代码:

    def get_form_data(self):
vals = {}.fromkeys(self.mapper.keys(),False)
ctrls = dict([(x._name,x) for x in self.input_ctrls])
for k,v in self.mapper.items():
ctrl = ctrls.get(v,False)
if ctrl and ctrl.get():
vals.update({k:ctrl.get()})
#print vals
logging.debug('product form data:%s'%vals)
return vals

关于input_ctrls的说明,因为控件的从属关系,本质上应该是一个树。

可以采用一个设计:

将控件放入到frame中,所有的frame放入到一个列表中frame_list。

frame中的控件用grid方式布局。于是就有了以下读取界面上所有输入控件的代码:

    def _is_input(self, ctrl_obj):
"""
是否为输入控件
:param ctrl_obj:
:return:
"""
if ctrl_obj:
name = ctrl_obj._name
matches= ['txt_','cb_']
if (name.split('_')[0]+'_') in matches:
return True
return False def _get_input_ctrls(self, container):
if container:
cs = container.grid_slaves()
cs.extend(container.pack_slaves())
for c in cs:
if self._is_input(c):
self.input_ctrls.append(c)
else:
self._get_input_ctrls(c) def get_input_ctrls(self):
self.input_ctrls=[]
for f in self.frames:
self._get_input_ctrls(f)
return self.input_ctrls

 是否输入控件采用了根据_name属性进行的判断。此处需要有coding规范约束。

实际上可以改写_is_input逻辑,根据__class__来进行枚举判断。

相应的设置表单的值逻辑如下:

    def set_data(self, data):
if not isinstance(data,dict):
raise TypeError
if not self.mapper:
raise "set_mapper method must be called before this method being called."
ctrls = dict([(x._name,x) for x in self.get_input_ctrls()])
for k,v in self.mapper.items():
if True:#data.get(k,None) is not None:
ctrl_obj = ctrls.get(v)
if ctrl_obj:
state = ctrl_obj['state']
ctrl_obj.configure(state='normal')
if isinstance(ctrl_obj,NewCBtn):
ctrl_obj.checked(data.get(k))
elif isinstance(ctrl_obj,NewCBox):
vals = data.get(k)
if isinstance(vals,(list,tuple)):
val= vals[-]
if not ctrl_obj.dictionary:
t={vals[-]:vals[]}
ctrl_obj.set_dict(t)
ctrl_obj.set(val)
else:
ctrl_obj.value(vals)
elif isinstance(ctrl_obj,NewImage):
ctrl_obj.Image(data.get(k))
elif isinstance(ctrl_obj,Text):
ctrl_obj.delete("1.0",END)
ctrl_obj.insert("1.0",data.get(k))
elif isinstance(ctrl_obj,Entry):
ctrl_obj.delete(,END)
ctrl_obj.insert(, str(data.get(k) or ''))
else:
logging.warning('unkown control type object:%s'%ctrl_obj.__class__.__name__) ctrl_obj.configure(state=state)

其中,类Newxxx为自己定义的类:

NewCBox

class NewCBox(ttk.Combobox):
def __init__(self, master, dictionary={}, *args, **kw):
if not kw:kw={'values':sorted(list(dictionary.keys()))}
else:kw.update({'values':sorted(list(dictionary.keys()))})
ttk.Combobox.__init__(self, master, *args, **kw)
self.dictionary = dictionary
#self.bind('<<ComboboxSelected>>', self.selected) #purely for testing purposes
self.bind('<Control-a>', self.select_all_input) def select_all_input(self,event):
#选择输入文本,不起作用
#print 'Ctrl+A'
text = self.get()
vals = self.cget('values')
for i in range(len(vals)):
if vals[i]==text:
self.current(i) def set_dict(self, dictionary):
self.dictionary=dictionary
self['values']= sorted(list(dictionary.keys())) def value(self,new_val=None):
if new_val is None:
key = self.get()
d= self.dictionary
k1=key.encode('UTF-8')#ASCII码就是UTF-8编码的最少字节的版本
k2=key.encode('GB2312')
k3=key.encode('CP936')
return d.get(key,d.get(k1,d.get(k2,d.get(k3,False))))else:
for k,v in self.dictionary.items():
if str(new_val)==str(v):
self.set(k)
return k
# def selected(self, event): #Just to test
# print(self.value())

NewImage

import io
class NewImage(Label):
def __init__(self, master=None,image_path=r'nullImage.png', cnf={}, **kw):
image = Image.open(image_path)
self.default_image = ImageTk.PhotoImage(image)
self.current_image = self.default_image
Label.__init__(self, image=self.current_image, master=master, cnf=cnf,**kw) def Image(self,base64_source=None,encoding='base64'):
if not base64_source is None:
if base64_source:
base64_source = resize_img(base64_source,size=(100,100))
image_stream = io.BytesIO(base64_source.decode(encoding))
image = Image.open(image_stream)
self.current_image =ImageTk.PhotoImage(image)#PhotoImage(file='pro.gif')# PhotoImage(data=background_stream.getvalue())
self['image']=self.current_image
else:
self['image']=self.default_image
return self['image']

NewCBtn

class NewCBtn(Checkbutton):
def __init__(self, master,*args, **kw):
self.value = IntVar()
if not kw:kw={'variable':self.value}
else:kw.update({'variable':self.value})
Checkbutton.__init__(self,master,*args,**kw) def checked(self,value=None):
if value is not None:
self.value.set(value and 1 or 0)
return self.value.get()

python gui之tkinter界面设计pythonic设计的更多相关文章

  1. Python GUI编程(Tkinter) windows界面开发

    Python实现GUI简单的来说可以调用Tkinter库,这样一般的需求都可以实现,显示简单的windows窗口代码如下: python_gui.py 1 #!C:\Python27\python.e ...

  2. Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介

    Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...

  3. Python GUI with Tkinter (from youtube) 在youtube上能找到很多编程视频...

    Python GUI with Tkinter - 1 - Introduction以上链接是一个python tkinter视频系列的第一讲的链接.虽然英语不好,但是,程序还是看得懂的(照着做就可以 ...

  4. Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)

    一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 二.Tkinter 是什么 三.Tkinter 控件详细介绍 1. T ...

  5. Python GUI工具Tkinter以及拖拉工具Page安装

    如果使用Tkinter作为Python GUI工具,我们需要安装Tkinter,这个使用conda或者pip即可: conda install -c anaconda tk 为了提高界面编写效率,可以 ...

  6. python GUI学习——Tkinter

    支持python的常见GUI工具包: Tkinter 使用Tk平台 很容易得到 半标准 wxpython 基于wxWindows.跨平台越来越流行 Python Win 只能在Windows上使用 使 ...

  7. Python -- Gui编程 -- Tkinter的使用 -- 基本控件

    1.按钮 tkBtton.py import tkinter root = tkinter.Tk() btn1 = tkinter.Button(root, anchor=tkinter.E,\ te ...

  8. Python:GUI之tkinter学习笔记2界面布局显示

    相关内容: pack 介绍 常用参数 使用情况 常用函数 grid 介绍 常用参数 使用情况 常用函数 place 介绍 常用参数 使用情况 常用函数 首发时间:2018-03-04 14:20 pa ...

  9. python GUI编程tkinter示例之目录树遍历工具

    摘录 python核心编程 本节我们将展示一个中级的tkinter应用实例,这个应用是一个目录树遍历工具:它会从当前目录开始,提供一个文件列表,双击列表中任意的其他目录,就会使得工具切换到新目录中,用 ...

随机推荐

  1. CV界的明星人物们

    CV界的明星人物们 来自:http://blog.csdn.net/necrazy/article/details/9380151,另外根据自己关注的地方,加了点东西. 今天在cvchina论坛上看到 ...

  2. cmake 编译 c++ dll 的一个例子(更新2:增加 python 调用方法)

    CMakeLists.txt project(xxx) add_library(xxx SHARED xxx.cpp) add_executable(yyy yyy.cpp) target_link_ ...

  3. tar: 由于前次错误,将以上次的错误状态退出

    1.安装cmake的源码包,出现以下错误提示: # tar -zxvf cmake-3.2.2.tar.gz cmake-/Source/cmCommandArgumentParser.cxx tar ...

  4. spring mvc3的注解@ResponseBody 自动返回jason

    第三种利用spring mvc3的注解@ResponseBody 例如: @ResponseBody @RequestMapping("/list") public List< ...

  5. SSDB 数据库

    SSDB数据库 SSDB是一套基于LevelDB存储引擎的非关系型数据库(NOSQL),可用于取代Redis,更适合海量数据的存储. 另外,rocksdb是FB在LevelDB的二次开发版本,因此也存 ...

  6. 【转】跟我学Kafka之NIO通信机制

    from:云栖社区 玛德,今天又被人打脸了,小看人,艹,确实,相对比起来,在某些方面差一点,,,,该好好捋捋了,强化下短板,规划下日程,,,引以为耻,铭记于心. 跟我学Kafka之NIO通信机制   ...

  7. javascript位运算

    javascript作为一门高级语言,他尽量让开发人员减少思考底层的硬件工作原理,而将精力集中在逻辑开发的层面.不过,不论这门语言多么高级,我们必须知道数据依然以bits的形式存储,有时候我们会直接与 ...

  8. spring 缓存(spring自带Cache)(入门)源码解读

    spring自带的缓存类有两个基础类:Cache(org.springframework.cache.Cache)类,CacheManager(org.springframework.cache.Ca ...

  9. 湖南国庆模拟赛day1 分组

    题目大意:给你一个n个数的数列s,要对这些数进行分组,当有任意两个数在一种方案在一起而在另一种方案中不在一起算是两种不同的方案,一个组的"不和谐程度"为组内数的极差,如果只有一个人 ...

  10. java 在接口里函数不能重载?

    项目里使用hession远程调用serviceRemote接口,而serviceRemote接口里有两个save方法,参数分别是CpCredential对象和List,但运行发现会报莫名其妙的错. 后 ...