隨手寫的,后續整理。
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[i] 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[i] 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[i], 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[i]==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,謝謝。