2013年8月18日 星期日

Python GUI in Tkinter

過去也曾透過Java Swing進行GUI Programming,2008年工作時上需要透過Python來開發GUI。從沒寫過Python 到開始寫用Tkinter來開發GUI程式,大概花了幾天。 目前,撰寫plus-in讓Python能夠透過去連Serial Console, 另外還把一些C的Header檔案和陣列的宣告和使用進行簡易的 Parsing和Link並resolve出一些Constants的值以及Configuration資訊。 接著根據這些資訊透過Python自動產生GUI。

說實在的,我用的很不習慣。特別是它的Layout只有三種管理的方式Pack、Grid、Place三種,讓我覺得Twinter不是非常直覺。我是覺得用它來寫一些簡單方便的GUI還可以,如果要拿來寫複雜的視窗程式 可能會花很多時間。否則就要另外在包一層這樣用起來會比較順手。

Tkinter主要的事件反應都是透過configure每個Widget所對應的處理函數。以Button來說,透過指定command對應的函數,當Button發生press事件時會呼叫對應的函數。

以下這張圖是Demo1.py執行的結果,這個範例中SHOW_JF1、SHOW_JF2 與SHOW_JF3三個Button分別透過三種寫法來處理Button的事件反映。



Demo1.py的程式碼如下所示:

  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
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
from Tkinter import *

class ActionListener:
    main = None
    def __init__(self, main):
        self.main = main;

def action(self):
        print("ActionListener!");
        self.main.showJF2();

class Main:

    def __init__(self):   
        tk = Tk();
        self.mjf = Frame(tk, borderwidth = 3, relief=SUNKEN);   
        self.jf1 = Frame(self.mjf);
        self.jf1.configure(borderwidth = 3, background = "green", relief=GROOVE);

        bt1 = Button(self.jf1, text="JF1");
        bt2 = Button(self.jf1, text="JF1");
        bt3 = Button(self.jf1, text="JF1");
        bt1.pack(side = LEFT, fill=BOTH, expand=YES);
        bt2.pack(side = LEFT, fill=BOTH, expand=YES);
        bt3.pack(side = LEFT, fill=BOTH, expand=YES);


        self.jf2 = Frame(self.mjf);
        self.jf2.configure(borderwidth = 3, background = "red", relief=RIDGE);

        bt1 = Button(self.jf2, text="JF2");
        bt2 = Button(self.jf2, text="JF2");
        bt3 = Button(self.jf2, text="JF2");
        bt1.pack(side = LEFT, fill=BOTH, expand=YES);
        bt2.pack(side = LEFT, fill=BOTH, expand=YES);
        bt3.pack(side = LEFT, fill=BOTH, expand=YES);        



        self.jf3 = Frame(self.mjf);
        self.jf3.configure(borderwidth = 3, background = "yellow", relief=RIDGE);
        bt1 = Button(self.jf3, text="JF3");
        bt2 = Button(self.jf3, text="JF3");
        bt3 = Button(self.jf3, text="JF3");
        bt1.pack(side = LEFT, fill=BOTH, expand=YES);
        bt2.pack(side = LEFT, fill=BOTH, expand=YES);
        bt3.pack(side = LEFT, fill=BOTH, expand=YES);

        btFrame = Frame(tk);
        bt1 = Button( btFrame, text="SHOW_JF1");
        bt2 = Button( btFrame, text="SHOW_JF2");
        bt3 = Button( btFrame, text="SHOW_JF3");
        
        #[ 1. Anonymous Callback Function with arguments
        bt1.configure(command = lambda s=self, event="JF1": s.showJF(event));

        #[ 2. ActionListener with arguments
        bt2.configure(command = ActionListener(self).action);

        #[ 3. Direct Callback Function
        bt3.configure(command = self.showJF3);

        bt1.pack(side = LEFT, fill=BOTH, expand=YES);
        bt2.pack(side = LEFT, fill=BOTH, expand=YES);
        bt3.pack(side = LEFT, fill=BOTH, expand=YES);

        btFrame.pack(side = TOP)
        self.mjf.pack(side = TOP, fill=BOTH, expand=YES);

        newBtFrame = Frame(tk);
        newBtFrame.pack(side = TOP ,fill=X, expand=YES);
        bt1 = Button( newBtFrame, text="Bottom Button1");
        bt2 = Button( newBtFrame, text="Bottom Button2");
        bt1.pack(side=LEFT);
        bt2.pack(side=RIGHT);

        self.showJF("JF2");

    def showJF(self, event):
        print("Anonymous Callback Function with arguments");
        if(self.currJF != None):
            self.currJF.pack_forget();

        if (event=="JF1"):
            self.jf1.pack(side = TOP, fill=BOTH, expand=YES);
            self.currJF = self.jf1;

        if (event=="JF2"):
            self.jf2.pack(side = TOP, fill=BOTH, expand=YES);
            self.currJF = self.jf2;

        if (event=="JF3"):
            self.jf3.pack(side = TOP, fill=BOTH, expand=YES);
            self.currJF = self.jf3;
           
    def showJF2(self):
        if(self.currJF != None):
            self.currJF.pack_forget();

        self.jf2.pack(side = TOP, fill=BOTH, expand=YES);
        self.currJF = self.jf2;

    def showJF3(self):
        if(self.currJF != None):
            self.currJF.pack_forget();

        self.jf3.pack(side = TOP, fill=BOTH, expand=YES);
        self.currJF = self.jf3;

def main():
    m = Main();
    mainloop();

Reference:

http://www.pythonware.com/library/an-introduction-to-tkinter.htm
http://effbot.org/tkinterbook/
http://www-acc.kek.jp/WWW-ACC-exp/KEKB/control/Activity/Python/TkIntro/introduction/index.htm


沒有留言:

張貼留言

歡迎留言討論與指教