Skip to content

Instantly share code, notes, and snippets.

@fogleman
Created January 14, 2016 23:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fogleman/d8787ed3e96aaf100774 to your computer and use it in GitHub Desktop.
Save fogleman/d8787ed3e96aaf100774 to your computer and use it in GitHub Desktop.
Simple Timer App
import bisect
import math
import random
import time
import wx
FONT = 'Courier'
MAX_SECONDS = 60 * 10
class Panel(wx.Panel):
def __init__(self, parent):
super(Panel, self).__init__(parent)
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.Bind(wx.EVT_SIZE, self.on_size)
self.Bind(wx.EVT_PAINT, self.on_paint)
self.Bind(wx.EVT_CHAR_HOOK, self.on_char)
self.reset()
self.update()
def reset(self):
self.frame = 0
self.start = None
self.done = False
def update(self):
if self.start is None:
delay = 100
elif self.done:
delay = 250
self.frame += 1
else:
delay = 100
self.Refresh()
wx.CallLater(delay, self.update)
def on_char(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE:
self.GetParent().Close()
if event.GetKeyCode() == wx.WXK_SPACE:
if self.start is None:
self.reset()
self.start = time.time()
else:
self.reset()
def on_size(self, event):
event.Skip()
self.Refresh()
def on_paint(self, event):
bg = wx.Colour(48, 48, 48)
if self.done and self.frame % 2:
bg = wx.WHITE
dc = wx.AutoBufferedPaintDC(self)
dc.SetBackground(wx.Brush(bg))
dc.Clear()
font = dc.GetFont()
font.SetFaceName(FONT)
dc.SetFont(font)
if self.start is None:
self.draw(dc, 'press space', 3)
else:
elapsed = time.time() - self.start
if MAX_SECONDS and elapsed >= MAX_SECONDS:
self.done = True
if self.done:
self.draw(dc, "TIME'S UP!", 8)
else:
seconds = int(elapsed)
s = seconds % 60
m = (seconds / 60) % 60
text = '%02d:%02d' % (m, s)
self.draw(dc, text, 8)
def fit_text(self, dc, width, height, text):
class Fitter(object):
def __init__(self, dc, step, width, height, text):
self.dc = dc
self.step = step
self.width = width
self.height = height
self.text = text
def __len__(self):
a = self.width / self.step
b = self.height / self.step
return max(a, b)
def __getitem__(self, index):
size = (index + 1) * self.step
font = self.dc.GetFont()
font.SetPointSize(size)
self.dc.SetFont(font)
tw, th = self.dc.GetTextExtent(self.text)
return int(tw > self.width or th > self.height)
def compute(self):
index = max(0, bisect.bisect(self, 0) - 1)
size = (index + 1) * self.step
return size
fitter = Fitter(dc, 8, width, height, text)
return fitter.compute()
def draw(self, dc, text, pad):
w, h = dc.GetSize()
pw, ph = w / pad, h / pad
size = self.fit_text(dc, w - pw, h / 2 - ph, text)
font = dc.GetFont()
font.SetPointSize(size)
dc.SetFont(font)
w1, h1 = dc.GetTextExtent(text)
x = w / 2 - w1 / 2
y = h / 2 - h1 / 2
self.draw_text(dc, text, x, y, 5)
def draw_text(self, dc, text, x, y, r):
bg, fg = wx.BLACK, wx.WHITE
if self.done and self.frame % 2:
bg, fg = fg, bg
dc.SetTextForeground(bg)
dc.DrawText(text, x + r, y + r)
dc.SetTextForeground(fg)
dc.DrawText(text, x, y)
def main():
app = wx.App(False)
frame = wx.Frame(None)
Panel(frame)
frame.Show()
# frame.ShowFullScreen(True)
app.MainLoop()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment