計時器

      在〈計時器〉中尚無留言

思考方向

如果想要在一個視窗中, 每隔1秒就將文字方塊裏的值加 1, 那這該如何處理呢.

依以往的經驗, 就在建構子裏使用一個變數 index, 再使用迴圈把index 一直加1, 每次加1後就將結果送到文字方塊裏, 這不就解決了嗎. 但想想, 這個執行緒一直在迴圈裏, 它怎麼會有空出來處理圖型畫面更新的事情呢.  所以整個畫面就會卡住, 不會更新數字

多執行緒

此時多執行緒就可以搬出來用了. 但如同其他程式語言, 最好不要使用新的執行緒更新UI裏的元件. 否則很容易因為共競而當機.

wxPython有三個 “執行緒安全” 的函式, 分別為 wx.PostEvent, wx.CallAfter和wx.CallLater. 這三個函數是等待UI主執行緒有空時, 才使用UI主執行緒進行UI的更新.

本章介紹wx.CallAfter的用法, 因為此法最為簡單. 下面的代碼中, 使用threading.Thread產生一個執行緒, 並利用target=runnable, 指派此執行緒要執行的任務.

在runnable方法中, 每隔1秒就要更新元件, 更新的工作就交給wx.CallAfter去執行.

import wx
import threading, time
class MainFrame(wx.Frame):
    def __init__(self, parent=None):
        wx.Frame.__init__(self, parent)
        self.Show()
        panel = wx.Panel(self)
        panel.SetBackgroundColour("yellow")
        wx.StaticText(panel, -1, "Timer",pos=(50, 23))
        self.txt = wx.TextCtrl(panel, -1, "", pos=(100, 20))
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        sizer.Add(panel, 1, wx.EXPAND)
        self.Layout()
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.runFlag = True
        t=threading.Thread(target=self.runnable)
        t.start()
    def runnable(self):
        index=0
        while(self.runFlag):
            index+=1
            wx.CallAfter(self.DrawUI, index)
            time.sleep(1)
    def DrawUI(self, i):
        self.txt.SetValue("%d" % i)
    def OnClose(self, event):
        self.runFlag = False
        self.Destroy()
app=wx.App()
frame=MainFrame()
app.MainLoop()

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *