设为首页 收藏本站
查看: 1127|回复: 0

[经验分享] python gui之tkinter语法杂记

[复制链接]

尚未签到

发表于 2015-11-29 12:20:16 | 显示全部楼层 |阅读模式
  随手写的,后续整理。
  1. Entry如何调用父类的__init__?
  以下错,原因后续分析



super(Your_Entry_Class, self).__init__(self,**kw)

  报错:TypeError: must be type, not instance 。 莫名其妙
  谷歌了下,解决方案如下



apply(Entry.__init__, (self, parent), **kw)

  即直接调用父类的__init__
  
  2. 如何将ttk treeview 的某一行转入编辑状态
  事实上,(python 3)treeview有一个readonly属性。但我用的是python 2。
  解决方案:在双击treeview时根据鼠标的位置定位单元格,然后在此单元格里面贴入一个Entry控件即可。引用自stackoverflow。
  



    def on_detail_bom_line_db_click(self, event):
''' Executed, when a row is double-clicked. Opens
read-only EntryPopup above the item's column, so it is possible
to select text '''
# close previous popups
if self.entryPopup:
self.entryPopup.destroy()
# what row and column was clicked on

rowid = self.bom_lines.identify_row(event.y)
column = self.bom_lines.identify_column(event.x)
# clicked row parent id
parent = self.bom_lines.parent(rowid)
#print 'parent:'+parent
# do nothing if item is top-level
if parent == '':
pass
# get column position info
x,y,width,height = self.bom_lines.bbox(rowid, column)
# y-axis offset
pady = height // 2
# place Entry popup properly
url = self.bom_lines.item(rowid, 'text')
self.entryPopup = StickyEntry(self.bom_lines, url, width=12)
self.entryPopup.place( x=x, y=y+pady, anchor=W)
  扩展了Entry,添加了一点点行为:



class StickyEntry(Entry):
def __init__(self, parent, text, **kw):
''' If relwidth is set, then width is ignored '''
#fa = super(self,StickyEntry)
#fa.__init__(parent, **kw)
apply(Entry.__init__, (self, parent), kw)
self.insert(0, text)
#self['state'] = 'readonly'
self['readonlybackground'] = 'white'
self['selectbackground'] = '#1BA1E2'
self['exportselection'] = False
self.focus_force()
self.bind("<Control-a>", self.selectAll)
self.bind("<Escape>", lambda *ignore: self.destroy())
def selectAll(self, *ignore):
''' Set selection on the whole text '''
self.selection_range(0, 'end')
# returns 'break' to interrupt default key-bindings
return 'break'

  
  3. treeview 的 heigth属性咋回事?
  比如设置为60(pixels),结果抛出屏幕很多。 原因是这个是行数!!!
  
  4. Entry 的width似乎也不是像素为单位的!
  随便设置一个数字,比如20,能有200pixel或者更多的效果。
  经过验证,似乎是数字字符的个数(比如20,就刚好能放20个数字字符!)
  具体以什么字符为基准未知!
  
  5.如何给ttk treeview设置竖直滚动条?
  添加一个Srollbar控件,并将其set函数丢给treeview的yscrollcommand进行绑定。
  注意布局,Scrollbar控件最好紧挨着treeview,并且在右边。
  



vbar = ttk.ScrollBar(container, orient=VERTICAL, command = your_treeview.yview)
your_treeview.configure(yscrollcomand=vbar.set)
your_treeview.grid(row=0)
vbar.grid(row=0, column=1,sticky=NS)

  
  6. 如何将ttk treeview中的内容清空?
  调用其delete方法,如下:



items = your_treeview.get_children()
[your_treeview.delete(item) for item in items]

  
  7. 如何得到ttk treeview被双击的单元格的值?
    获取单元格的值,使用treeview的get函数即可,参数 (row, column) , row-- iid , column - index of column (started with '#')
  理论上讲,只通过控件是无解的。通过自己定义坐标边界的方式来解决,即给每一列定义宽度(像素单位)。event.x/y能够取到坐标。在分析此坐标落在哪一列的坐标范围内即可分析出。



    def get_cell_value(self, event, tree=None, col_widths=None):
"""
获取ttk treeview某一个单元格的值(在鼠标事件中)
:param event:
:param tree:
:param col_widths:
:return:
"""
if not tree:
tree = self.bom_lines
if not col_widths:
col_widths=self.form_bom_line_widths
if not isinstance(event,Event):
raise Exception("event must type of Tkinter.Event")
x= event.x
y= event.y
row = tree.identify_row(y)
vals = tree.item(row, 'values')
index = -1
for i in range(len(col_widths)):
if x>=0:
x-=col_widths
else:
index=i-1
break
if index!=-1:
return vals[index]
return False

  后记:实际上是本人疏忽,有一个identify_column的函数可以用来根据x的值定位具体的列。因此上述代码属于重复造轮子。



your_treeview.identify_column(event.x)

  
  8. 如何设置ttk treeview中某一个单元格的值?
  跟上面一样,通过event.x的所在区间得到列的index,然后调用treeview的set方法即可。代码如下:



    def set_cell_value(self, event, value, tree=None, col_widths=None):
"""
设置ttk treeview某一个单元格的值(在鼠标事件中)
:param event:
:param value:要设置的值
:param tree:
:param col_widths:
:return:
"""
if not tree:
tree = self.bom_lines
if not col_widths:
col_widths=self.form_bom_line_widths
if not isinstance(event,Event):
raise Exception("event must type of Tkinter.Event")
x= event.x
y= event.y
row = tree.identify_row(y)
index = -1
for i in range(len(col_widths)):
if x>=0:
x-=col_widths
else:
index=i-1
break
if index!=-1:
tree.set(row,column=index,value=value)
return True
return False

  
  9. Entry 如何设置选中文本的背景色?
  比如设置为红色(警示作用)



#choice 1:Entry的子类的__init__方法中
self['selectbackground']='red'
#choice 2:Entry实例ent
ent.config(selectbackground='red')

  
  10. ttk treeview的样式设定
  奇数行背景浅蓝色。有一个问题,就是选中了奇数行后,其背景色不变!暂时未破解。



    def brush_treeview(self, tv):
"""
改变treeview样式
:param tv:
:return:
"""
if not isinstance(tv, ttk.Treeview):
raise Exception("argument tv of method bursh_treeview must be instance of ttk.TreeView")
#=============给bom_lines设置样式=====
items = tv.get_children()
for i in range(len(items)):
if i%2==1:
tv.item(items, tags=('oddrow'))
tv.tag_configure('oddrow', background='#eeeeff')

  TAG OPTIONS


  • -foreground
  • -background
  • -font
  • -image
  11. 如何通过鼠标的滚轮控制scrollbar的滚动?
  默认情况下,是没有这种关联的。
  似乎tk框架中没法处理。此问题先放着。
  
  12.如何绑定数据到下拉框,并能够进行数据的模糊搜索定位?
  可以使用ttk的Combobox, 对其进行事件绑定(比如Return事件),demo如下:



self.cb_product_id.bind('<Return>', self.on_search_product_id)

  实际处理:



    def on_search_product_id(self,event):
product_no = self.cb_product_id.get()
res = self.bom.product_search(condition="name_template ilike '%%"+product_no+"%%' ", limit=20 )
self.cb_product_id['values']=[x[1] for x in res]

  有一个问题就是,这个values只有text,通常web的selection都会有(value,text)这样的组合,这里有些小不足。弥补的方法就是继承Combobox,如下:



class NewCBox(ttk.Combobox):
def __init__(self, master, dictionary={}, *args, **kw):
ttk.Combobox.__init__(self, master, values = sorted(list(dictionary.keys())),  *args, **kw)
self.dictionary = dictionary
self.bind('<<ComboboxSelected>>', self.selected) #purely for testing purposes
def set_dict(self, dictionary):
self.dictionary=dictionary
self['values']= sorted(list(dictionary.keys()))
def value(self):
return self.dictionary[self.get()]
def selected(self, event): #Just to test
print(self.value())

  
  
  13.如何用代码打开Combobox的列表?
  demo代码,引用自这里。原理:直接丢事件,使用event_generate函数。



from Tkinter import *
import ttk
root = Tk()
c = ttk.Combobox(root)
c.pack()
c['values'] = ['1','2','3']
def dropdown():
c.event_generate('<Button-1>')
b = Button(root, text='test', command=dropdown)
b.pack()

root.mainloop()

  
  14. 如何将两个长度相同的list用一句代码合成一个dict?



my_dict = dict(list(zip(list1,list2)))

  其中list1将作为key,list2将作为value
  即使用zip压缩为元组(key,value),然后用dict生成字典。
  
  15. 如何实现Combobox的onchange事件的处理?
  通过<<ComboboxSelected>>事件来处理,如下代码:



your_combobox.bind('<<ComboboxSelected>>',your_select)
def your_select(event):
pass

  
   16. 如何设置Combobox的默认选项?
  使用Combobox的current函数即可,如下:



default_index=0
your_combobox.current(default_index)

  
  17. 如何通过代码选中Combobox中输入的所有文本,通过Control + A键组合。
  entry可以通过selection_range(0, 'end')实现。combobox是没有这个操作支持的。只能够曲线救国了。
  通过选择对应的选项来实现。尝试以下代码无果而终。此问题先放着。



    my_combobox.bind('<Control-a>', 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==text:
self.current(i)

  
  18. 默认全部展开ttk treeview的节点,该如何实现?



treeview.item("Main", open=False)

  即直接修改每个item的open选项。通过treeview.tv.event_generate("<<TreeviewOpen>>")是没有作用的。



    def expand_tree(self, tv, root_id):
iids = tv.get_children(root_id)
for iid in iids:
tv.item(iid,open=True)
self.expand_tree(tv, iid)

  
  19. 如何实现其他键盘事件?
  ctrl+f/g等等。直接绑定就好,语法如下:
  <Control-key> ,其中key就是相应的字符。例如ctrl+f的绑定如下:



your_treeview.bind('<Control-f>', find_something)

  
  20. 如何实现弹出式的输入框?
  没有现成的控件,做一个就好了。以下是一个搜索框:



class PopupEntry:
def __init__(self, parent=None,default_value='', callback=None):
self.callback = callback
self.top = Toplevel(parent)
Label(self.top, text="请输入:").grid(row=0)
self.e = Entry(self.top)
self.e.grid(row=0,column=1)
Button(self.top, text="确定", command=self.ok).grid(row=1)
Button(self.top, text="取消", command=self.top.destroy).grid(row=1,column=1)
self.__set(default_value)
self.e.bind('<Double-1>', lambda *args:self.e.delete(0,END))
self.e.bind('<Return>', self.on_return)
self.top.maxsize(200,60)
self.top.resizable(False,False)
self.top.title('搜索')
def on_return(self,event):
self.ok()
def ok(self):
#print "value is", self.e.get()
if self.callback and callable(self.callback):
self.callback(self.e.get())
self.top.destroy()

  关于窗口的细节控制,发现了一个不错的资源。这里。
  
  21. 弹出的TopLevel窗口如何设置焦点?
  这里有解答。即调用grab_set。 不过这个方案貌似在win7下面不起作用。
  解决方案:TopLevel里面的控件调用focus方法。比如,输入框



your_entry.focus()
  
   22. 如何选中ttk treeview的多行数据?



tree_view.selection_set(items)

  注意,items是iids,即以I开头的行的id编码的元组。
  
  23. 如何设置右键菜单?



context_menu = Menu(self.tv, tearoff=0)
context_menu.add_command(label="复制", command=copy_handler)
some_widget.bind('<3>', show_context_menu)
def show_context_menu(event):
context_menu.post(event.x_root,event.y_root)
def copy_handler():
pass

  
  24.如何用python操作剪贴板?
  https://pypi.python.org/pypi/clipboard/



import clipboard
clipboard.copy("abc")  # now the clipboard content will be string "abc"
text = clipboard.paste()  # text will have the content of clipboard

  需要安装额外的包,原生貌似不支持。
  在windows上还有一个方法,参考这里。在我的机器上会报错。暂时不折腾,避免安装多余的包。
  
  25. 如何改变Label的值?



your_label['text']='new value'# or
your_label.configure(text='new value')

  
  26. 如何定位到ttk treeview的某行?
  使用treeview的yview_moveto函数,yview_moveto(fraction)
  fraction ,float类型, [0~1.0]。例如定位到最后一行,如下:



your_Treeview.yview_moveto(1.0)

  
  
  27. 如何在右键菜单中添加分隔符?



your_menu.add_seperator()

  
  28. 如何设置checkbutton的checked属性?
  要设置variable属性,那么窗体类中需要记录这个属性。如果有多个checkbox,那么必须有多个类变量类记录他们。
  这样很不pythonic。好吧,把它扩展下,如下:



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()

  
  29. 如何删除Text中的文本?
  很诡秘的写法:



your_text.delete("1.0",END)

  而Entry中如此删除:



your_entry.delete(0,END)

  所以Text的删除有点火星人的作风。
  
  29. 为何以下逻辑进入第一个分支?



from Tkinter import *
root = Tk()
b = Combobox(root)
if isinstance(ctrl,Entry):
print "Entry"
elif isinstance(ctrl,Combobox):
print "Combobox"
else:
print unkown

  因为Combobox是Entry的子类。所以对于有继承关系的判断分支,孙子应该放在最前面,防止被父亲或者祖父给短路了。
  
  30. tk中图像的处理?
  常规方法是用Label,设置其image属性。由于涉及到了变量(图片)的生命周期问题,因而把它封装为一个类,如下:



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)
self['image']=self.current_image
else:
self['image']=self.default_image
return self['image']

  
   31.如何禁止窗口最大化?
  对于窗体来说,有一个resizable方法,接受两个参数(x_resizable,y_resizable),分别表示横向和纵向是否可以拉伸。
  
  32. 如何设置Label的字体颜色?
  foreground  -- fg (字体颜色,前景色)
  background -- bg(底色,背景色)
  例如设置蓝色,如下:



Label(text='your_label', fg='blue').pack()

  
  33. 如何设置Label的字体?



import tkFont
...
ft1 = tkFont.Font(family = 'Fixdsys',size = 10,weight = tkFont.BOLD)
Label(f, text=u'产品编号(*)', fg='blue', font=ft1).grid(row=1,column=1, sticky=W)

  Fixdsys表示系统字体
  
  34. 如何获取控件相对于屏幕的坐标?
  ctrl.winfo_rootx()/winfo_rooty()
  例如,entry



my_entry.winfo_rootx()

  得到的就是my_entry这个输入框的左上角的x坐标(相对于屏幕)
  相对于父容器,则用
  ctrl.winfo_x()/winfo_y()
  
  35. 如何隐藏窗口的标题栏?
  只对Toplevel有效,使用其overrideredirect方法。
  demo代码:



from Tkinter import *
root = Tk()
top = Toplevel(root)
top.overrideredirect(True)
root.mainloop()

  
  36. ttk treeview如何隐藏几列?如何设置隐藏的列的值?如何设置显示的列的值?
  隐藏:
  在构造函数里面有一个参数 displaycolumns=['c1','c2',...,'cn'],设置显示的列。 columns=['c1','c2',...,'cm']设置所有的列(m>n)。
  那么 n+1 ~ m都是隐藏的列。
  设置隐藏列的值:
  没有直接的函数,只能通过 treeview.item(iid, values=new_value_list)来设置所有列的值(包括隐藏列)
  设置显示列的值:
  有一个set函数, treeview.set(row,column,value)
  
  37. ttk treeview 如何隐藏第一列?
  构造函数里面的选项 show=['headings']即可。

  38. 如何隐藏指定行?
  暂时无解。
  39. 如何得到treeview中被选中的行?
  通过selection方法而不是selection_get方法,即:



your_treeview.selection()

  这样得到的是一个iid的list。
  
  40. treeview.delete?
  删除多个元素时以下写法会报错,莫名其妙



iids = your_treeview.selection()
your_treeview.delete(iids)
  
  错误信息,iids中的item无法找到,而只能按照上述记录6的方式进行。
  
  41. 如何用模拟treeview的单击事件?
  比如单击某一行。



your_treeview.event_generate('<1>',x=1,y=1)

  x=1,y=1为鼠标单击的坐标,根据具体情况而定。event_generate的**kw参数可以接受以下值:
  -when, -above, -borderwidth, -button, -count, -data, -delta, -detail, -focus, -height, -keycode, -keysym, -mode, -override, -place, -root, -rootx, -rooty, -sendevent, -serial, -state, -subwindow, -time, -warp, -width, -window, -x, or -y
  
   42. 如何中断事件链?
  比如treeview的<1>时间后,紧接着是<<TreeviewSelected>>。
  Combobox 的键盘事件后,还有其他事件阻止Ctrl-A实现全选的效果。
  执行到一个事件,同时不需要再执行后面的事件,可以返回'break'进行中断,如下:



def some_event(self,event):
#do something
return 'break'

  
  43. 如何disable右键菜单里面的某个命令?
  使用mehu的entryconfigure方法,demo如下:



from Tkinter import *
root = Tk()
#panel = Frame(root)
#panel.pack()
m = Menu(root,tearoff=0)
m.add_command(label='test1')
m.add_command(label='test2')
def context_menu(event):
m.post(event.x,event.y)

root.geometry("400x400+0+0")
root.bind('<3>',context_menu)
m.entryconfigure(1,state='disabled')
root.mainloop()

  
  44. 如何遍历Menu的菜单项?
  暂时无解。
  
  45. 如何打开一个选择文件对话框?
  详细资料参考这里。主要使用tkFileDialog模块的askopenfilename方法。demo如下:



# -*- coding: CP936 -*-
from Tkinter import *
from tkFileDialog import *
root = Tk()
filename=askopenfilename(parent = root)
print filename
root.mainloop()

  
  
  转载请注明本文来自http://www.cnblogs.com/Tommy-Yu/p/4171006.html,谢谢。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-144909-1-1.html 上篇帖子: python基础教程学习笔记---(2)列表和元组 下篇帖子: Python——Matplotlib模块在Windows下安装
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表