2013年7月12日 星期五

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官網文件好像就很不錯了,已補上,發現什麼的話,此篇隨時會更新 :)

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,如下
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)

2 則留言: