wxPython wx.Timerを使ってグラフィック描画してみる
wx.Timerを使ってカウントアップタイマーを表示し、カウントアップに応じてグラフィックの棒グラフを描画してみる。どこかに埋もれて無くなってしまう前にメモしておく。
参考にしたリンク
ウィンドウに、1から999までのカウントアップ値を表示させ、カウントの値に応じて1,10,100の位の棒グラフを描画する。最初はwx.ClientDCを使って描画し、次にwx.BufferedDCを使って、フリッカーノイズを対策してみる。
#!/usr/bin/env python
#coding:utf-8
import wx
class MyWindow(wx.Frame):
def __init__(self, parent=None, id=-1, title=None):
wx.Frame.__init__(self, parent, id, title)
self.panel = wx.Panel(self, size=(300, 200))
self.panel.SetBackgroundColour('WHITE')
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer)
self.Fit()
self.counter = 0
self.timer.Start(50)
def OnTimer(self, event):
self.counter += 1
if self.counter == 999:
self.timer.Stop()
pos_x = 30
pos_cnt_y = 20
g_height = 40
g_width = 28
pos_g1_y = pos_cnt_y + g_height
pos_g2_y = pos_g1_y + g_height
pos_g3_y = pos_g2_y + g_height
cnt_str = "%03d" % self.counter
g_width1 = int(cnt_str[2]) * g_width
g_width2 = int(cnt_str[1]) * g_width
g_width3 = int(cnt_str[0]) * g_width
dc = wx.ClientDC(self.panel)
dc.Clear()
dc.SetTextForeground('green')
font = wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
dc.SetFont(font)
dc.DrawText(cnt_str, pos_x, pos_cnt_y)
dc.SetPen(wx.Pen('blue'))
dc.SetBrush(wx.Brush('blue'))
dc.DrawRectangle(pos_x, pos_g1_y, g_width1, g_height)
dc.SetPen(wx.Pen('red'))
dc.SetBrush(wx.Brush('red'))
dc.DrawRectangle(pos_x, pos_g2_y, g_width2, g_height)
dc.SetPen(wx.Pen('yellow'))
dc.SetBrush(wx.Brush('yellow'))
dc.DrawRectangle(pos_x, pos_g3_y, g_width3, g_height)
if __name__ == '__main__':
app = wx.PySimpleApp()
w = MyWindow(title='wxgr-timer1')
w.Center()
w.Show()
app.MainLoop()
メモ
- テキストの色を変更するにはSetTextForegroundメソッドをコールする。
- テキストの文字サイズを変更するには、サイズを指定してwx.Fontでfontオブジェクトを作成し、デバイスコンテキストオブジェクトのSetFontメソッドをコールする。
- テキストを表示するにはDrawTextメソッドをコールする。
実行すると
フリッカーノイズ対策した描画
#!/usr/bin/env python
#coding:utf-8
import wx
class MyWindow(wx.Frame):
def __init__(self, parent=None, id=-1, title=None):
wx.Frame.__init__(self, parent, id, title)
self.panel = wx.Panel(self, size=(300, 200))
self.panel.SetBackgroundColour('WHITE')
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer)
self.Fit()
self.counter = 0
self.timer.Start(50)
def OnTimer(self, event):
self.counter += 1
if self.counter == 999:
self.timer.Stop()
pos_x = 30
pos_cnt_y = 20
g_height = 40
g_width = 28
pos_g1_y = pos_cnt_y + g_height
pos_g2_y = pos_g1_y + g_height
pos_g3_y = pos_g2_y + g_height
cnt_str = "%03d" % self.counter
g_width1 = int(cnt_str[2]) * g_width
g_width2 = int(cnt_str[1]) * g_width
g_width3 = int(cnt_str[0]) * g_width
cdc = wx.ClientDC(self.panel)
bmp_w, bmp_h = self.panel.GetSize()
bmp = wx.EmptyBitmap(bmp_w, bmp_h)
bdc = wx.BufferedDC(cdc, bmp)
bdc.Clear()
bdc.SetTextForeground('green')
font = wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
bdc.SetFont(font)
bdc.DrawText(cnt_str, pos_x, pos_cnt_y)
bdc.SetPen(wx.Pen('blue'))
bdc.SetBrush(wx.Brush('blue'))
bdc.DrawRectangle(pos_x, pos_g1_y, g_width1, g_height)
bdc.SetPen(wx.Pen('red'))
bdc.SetBrush(wx.Brush('red'))
bdc.DrawRectangle(pos_x, pos_g2_y, g_width2, g_height)
bdc.SetPen(wx.Pen('yellow'))
bdc.SetBrush(wx.Brush('yellow'))
bdc.DrawRectangle(pos_x, pos_g3_y, g_width3, g_height)
cdc.DrawBitmap(bmp,0,0)
if __name__ == '__main__':
app = wx.PySimpleApp()
w = MyWindow(title='wxgr-timer2(no flicker)')
w.Center()
w.Show()
app.MainLoop()
メモ
- フリッカーノイズを発生させないためにwx.BufferedDCを使う
- まず、wx.ClientDCオブジェクトを作成する。
- 次に、wx.EmptyBitmapでビットマップバッファーを作成し、これを指定したwx.BufferedDCオブジェクトを作成する。
- wx.BufferedDCオブジェクトに対してグラフィックを描画する。
- ClientDCオブジェクトのDrawBitmapメソッドをコールして、描画済みのビットマップを表示させる。いちいち描画しないのでフリッカーノイズは発生しない。


