tkinter 雜記

最近想要用python寫個GUI的聊天軟體,於是在網路上查了一些資料,似乎pyQT滿受歡迎的,只是本人我一直以來有個毛病,就是不喜歡在電腦裝東裝西的 :) 因此決定使用python標準庫裡面的tkinter,只是剛開始不知從何下手的我,搜尋了很久,發現似乎沒有個很全面的文件,都是零零碎碎的,於是記錄一下目前發現的幾個reference

http://thinkingtkinter.sourceforge.net/
http://infohost.nmt.edu/tcc/help/pubs/tkinter.pdf
http://www.tkdocs.com/
http://docs.python.org/3.2/library/tkinter.html

大概要花一些時間來研究一下,才能有心得。
總之就先來個無聊的hello world吧 :-S
剛剛發現其實python官網文件好像就很不錯了,已補上,發現什麼的話,此篇隨時會更新 :)

1
2
3
4
5
6
7
8
9
10
11
12
from tkinter import *  
from tkinter import ttk
from tkinter.ttk import *

def main():
root = Tk()
style = ttk.Style().configure('TLabel', foreground='black', background='green')
ttk.Label(root, text='Hello World').grid()
root.mainloop()

if __name__ == '__main__':
main()

已發現 http://www.tcl.tk/man/tcl8.5/TkCmd/grid.htm 這是tcl/tk的官方文件,從這裡就可以查到你所有想要的關於tkinter的reference。

#追加目前為止的心得,從網路上學了一些關於tkinter使用到的原理,也照著教學,寫了一個嘗試的code,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from tkinter import *
from tkinter import ttk


def main():
root = Tk()

content = ttk.Frame(root, padding=(3, 3, 12, 12))
frame = ttk.Frame(
content, borderwidth=7, relief='solid', width=200, height=100)
namelbl = ttk.Label(content, text='Name')
name = ttk.Entry(content)

onevar = BooleanVar()
twovar = BooleanVar()
threevar = BooleanVar()

onevar.set(True)
twovar.set(False)
threevar.set(True)

one = ttk.Checkbutton(content, text='one', variable=onevar, onvalue=True)
two = ttk.Checkbutton(content, text='two', variable=twovar, onvalue=True)
three = ttk.Checkbutton(
content, text='three', variable=threevar, onvalue=True)

ok = ttk.Button(content, text='OK')
cancel = ttk.Button(content, text='Cancel')

content.grid(column=0, row=0, sticky=(N, S, E, W))
frame.grid(column=0, row=0, columnspan=3, rowspan=2, sticky=(N, S, E, W))
namelbl.grid(column=3, row=0, columnspan=2, sticky=(N, W), padx=5)
name.grid(column=3, row=1, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
one.grid(column=0, row=3) # row=2 seems the same
two.grid(column=1, row=3)
three.grid(column=2, row=3)
ok.grid(column=3, row=3)
cancel.grid(column=4, row=3)

# when the window resized, all widget will be resized, too
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
content.columnconfigure(0, weight=3)
content.columnconfigure(1, weight=3)
content.columnconfigure(2, weight=3)
content.columnconfigure(3, weight=1)
content.columnconfigure(4, weight=1)
content.rowconfigure(1, weight=1)

root.mainloop()

if __name__ == '__main__':
main()

其實有稍微學過視窗程式設計的應該都知道,這類的都跑不掉有一個主迴圈,是用來處理event queue的,因此python tkinter也不例外 root.mainloop(),到目前為止,跟我以前用windows api寫的概念有所不同的是,tkinter他有所謂的 geometry management,是用來計算每個widget該放置的位置以及大小,geometry management 有三種

  1. place
  2. pack
  3. grid

從我看過的教學,pack是最早有的,它說功能強大(掩面 但是我不知道強在哪,place目前還沒用所以不清楚,最後grid是後來tkinter才出現的,但是它一出現後來很多人都用它,由此可見grid應該是比pack好用,因此我看的教學也是用grid居多,說穿grid頂多只是把視窗分成row和column這樣,方方格格,之後規定每個widget所在的row, column,以及它所跨越的row, column區間(ex. columnspan),這樣程式執行後,它就會自動計算每個widget的位置了~
至於columnconfigure and rowconfigure則是用來window resize的時候,它會讓裡面的元件,依照你規定的weight去放大( ex. weight=1 => 1 pixel to 1 pixel, weight=3 => 1 pixel to 3 pixel)