python gui之tkinter界面设计pythonic设计
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设计的更多相关文章
- Python GUI编程(Tkinter) windows界面开发
Python实现GUI简单的来说可以调用Tkinter库,这样一般的需求都可以实现,显示简单的windows窗口代码如下: python_gui.py 1 #!C:\Python27\python.e ...
- Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...
- Python GUI with Tkinter (from youtube) 在youtube上能找到很多编程视频...
Python GUI with Tkinter - 1 - Introduction以上链接是一个python tkinter视频系列的第一讲的链接.虽然英语不好,但是,程序还是看得懂的(照着做就可以 ...
- Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)
一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 二.Tkinter 是什么 三.Tkinter 控件详细介绍 1. T ...
- Python GUI工具Tkinter以及拖拉工具Page安装
如果使用Tkinter作为Python GUI工具,我们需要安装Tkinter,这个使用conda或者pip即可: conda install -c anaconda tk 为了提高界面编写效率,可以 ...
- python GUI学习——Tkinter
支持python的常见GUI工具包: Tkinter 使用Tk平台 很容易得到 半标准 wxpython 基于wxWindows.跨平台越来越流行 Python Win 只能在Windows上使用 使 ...
- Python -- Gui编程 -- Tkinter的使用 -- 基本控件
1.按钮 tkBtton.py import tkinter root = tkinter.Tk() btn1 = tkinter.Button(root, anchor=tkinter.E,\ te ...
- Python:GUI之tkinter学习笔记2界面布局显示
相关内容: pack 介绍 常用参数 使用情况 常用函数 grid 介绍 常用参数 使用情况 常用函数 place 介绍 常用参数 使用情况 常用函数 首发时间:2018-03-04 14:20 pa ...
- python GUI编程tkinter示例之目录树遍历工具
摘录 python核心编程 本节我们将展示一个中级的tkinter应用实例,这个应用是一个目录树遍历工具:它会从当前目录开始,提供一个文件列表,双击列表中任意的其他目录,就会使得工具切换到新目录中,用 ...
随机推荐
- cmake安装MySQL
发现一个网址整理的挺好,请各位参考: http://www.chenyudong.com/archives/building-mysql-5-6-from-source.html#i 也可以参考我的另 ...
- sqlserver检测死锁;杀死锁和进程;查看锁信息
http://blog.sina.com.cn/s/blog_9dcdd2020101nf4v.html sqlserver检测死锁;杀死锁和进程;查看锁信息 ( ::)转载▼ 标签: sql 检测死 ...
- JNDI全面总结
JNDI全面总结原理: 在DataSource中事先建立多个数据库连接,保存在数据库连接池中.当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池 ...
- Memcached【Magent+Memcached】集群
Memcached介绍 事件处理libevent是个程序库,它将Linux的epoll.BSD类操作系统的kqueue等事件处理功能封装成统一的接口.即使对服务器的连接数增加,也能发挥O(1)的性能 ...
- inline-block元素overflow:hidden对齐问题
inline-block元素设置overflow:hidden后,其本身会上移 解决方法:在该元素或其父元素上设置vertical-align:bottom 原因解释:inline-block元素被设 ...
- hdu3555 Bomb (记忆化搜索 数位DP)
http://acm.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others) Memory ...
- 在Linux下和Windows下遍历目录的方法及如何达成一致性操作
最近因为测试目的需要遍历一个目录下面的所有文件进行操作,主要是读每个文件的内容,只要知道文件名就OK了.在Java中直接用File类就可以搞定,因为Java中使用了组合模式,使得客户端对单个文件和文件 ...
- 遇到了IAR烧写程序出错,附解决办法The stack plug-in failed to set a breakpoint on "main"
今天做无线串口调试的时候用IAR7.51往CC2530无线模块烧程序的时候遇到了问题: 先是下载过程中有许多警告,然后就是提示无法跳断点,找不到main方法,每次烧程序都出现: The stack p ...
- POJ 3744 Scout YYF I
分段的概率DP+矩阵快速幂 Scout YYF I Time Limit: 1000MS Memory Limit: 65536K Total Sub ...
- php——文件下载
php——.doc 文件下载 先看简单实例: 同目录下有两个文件ib.php,test.php与供下载 .doc 文件: test.php文件内容: <?php $attr = glob(&qu ...