I have the following python modules. Sorry if the code is ugly. This is my first python GUI app and I'm fairly new to python as well. It's some sort of a count down timer with a todo list. It works kinda well except that after two minutes after running the program, it crashes with the following error:
Pango:ERROR:/build/buildd/pango1.0-1.28.0/pango/pango-layout.c:3739:pango_layout_check_lines: assertion failed: (!layout->log_attrs)
I have absolutely no idea what that even means. One I'm confused about is that it works after the first minute, ie. the timer label counts down ok but on the next minute, it crashes immediately.
After googling a bit, I think the issue might be related to multithreading? Any ideas?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Fri Jul 9 17:00:08 2010
import wx
import settimer
# begin wxGlade: extracode
# end wxGlade
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.todo1 = wx.TextCtrl(self, -1, "")
self.timer_label1 = wx.StaticText(self, -1, "00:00")
self.set_timer1 = wx.Button(self, -1, "Set Timer")
self.todo2 = wx.TextCtrl(self, -1, "")
self.timer_label2 = wx.StaticText(self, -1, "00:00")
self.set_timer2 = wx.Button(self, -1, "Set Timer")
self.todo3 = wx.TextCtrl(self, -1, "")
self.timer_label3 = wx.StaticText(self, -1, "00:00")
self.set_timer3 = wx.Button(self, -1, "Set Timer")
self.todo4 = wx.TextCtrl(self, -1, "")
self.timer_label4 = wx.StaticText(self, -1, "00:00")
self.set_timer4 = wx.Button(self, -1, "Set Timer")
self.todo5 = wx.TextCtrl(self, -1, "")
self.timer_label5 = wx.StaticText(self, -1, "00:00")
self.set_timer5 = wx.Button(self, -1, "Set Timer")
self.hours = 0
self.minutes = 0
self.__set_properties()
self.__do_layout()
self.Bind(wx.EVT_BUTTON, self.on_set1, self.set_timer1)
self.Bind(wx.EVT_BUTTON, self.on_set2, self.set_timer2)
self.Bind(wx.EVT_BUTTON, self.on_set3, self.set_timer3)
self.Bind(wx.EVT_BUTTON, self.on_set4, self.set_timer4)
self.Bind(wx.EVT_BUTTON, self.on_set5, self.set_timer5)
# end wxGlade
def __set_properties(self):
# begin wxGlade: MyFrame.__set_properties
self.SetTitle("Track Work")
self.todo1.SetMinSize((300, 25))
self.timer_label1.SetMinSize((100, 30))
self.timer_label1.SetFont(wx.Font(15, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
self.set_timer1.SetMinSize((85, 27))
self.todo2.SetMinSize((300, 25))
self.timer_label2.SetMinSize((100, 30))
self.timer_label2.SetFont(wx.Font(15, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
self.set_timer2.SetMinSize((85, 27))
self.todo3.SetMinSize((300, 25))
self.timer_label3.SetMinSize((100, 30))
self.timer_label3.SetFont(wx.Font(15, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
self.set_timer3.SetMinSize((85, 27))
self.todo4.SetMinSize((300, 25))
self.timer_label4.SetMinSize((100, 30))
self.timer_label4.SetFont(wx.Font(15, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
self.set_timer4.SetMinSize((85, 27))
self.todo5.SetMinSize((300, 25))
self.timer_label5.SetMinSize((100, 30))
self.timer_label5.SetFont(wx.Font(15, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
self.set_timer5.SetMinSize((85, 27))
# end wxGlade
def __do_layout(self):
# begin wxGlade: MyFrame.__do_layout
flex_sizer = wx.FlexGridSizer(5, 3, 2, 25)
flex_sizer.Add(self.todo1, 0, 0, 0)
flex_sizer.Add(self.timer_label1, 0, 0, 0)
flex_sizer.Add(self.set_timer1, 0, 0, 0)
flex_sizer.Add(self.todo2, 0, 0, 0)
flex_sizer.Add(self.timer_label2, 0, 0, 0)
flex_sizer.Add(self.set_timer2, 0, 0, 0)
flex_sizer.Add(self.todo3, 0, 0, 0)
flex_sizer.Add(self.timer_label3, 0, 0, 0)
flex_sizer.Add(self.set_timer3, 0, 0, 0)
flex_sizer.Add(self.todo4, 0, 0, 0)
flex_sizer.Add(self.timer_label4, 0, 0, 0)
flex_sizer.Add(self.set_timer4, 0, 0, 0)
flex_sizer.Add(self.todo5, 0, 0, 0)
flex_sizer.Add(self.timer_label5, 0, 0, 0)
flex_sizer.Add(self.set_timer5, 0, 0, 0)
self.SetSizer(flex_sizer)
flex_sizer.Fit(self)
self.Layout()
# end wxGlade
def on_set1(self, event): # wxGlade: MyFrame.<event_handler>
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
MyTimer = settimer.Timer(None, -1, "")
MyTimer.get_out_instance(self)
app.SetTopWindow(MyTimer)
MyTimer.Show()
app.MainLoop()
event.Skip()
def set_label(self):
self.timer_label1.SetLabel("%02d:%02d" % (self.hours, self.minutes))
self.minutes -= 1
# end of class MyFrame
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
main_frame = MyFrame(None, -1, "")
app.SetTopWindow(main_frame)
main_frame.Show()
app.MainLoop()
timer.py
import threading
import time
class Timer(threading.Thread):
def __init__(self, seconds, track):
threading.Thread.__init__(self)
self.total_time = seconds
self.track = track
def run(self):
for sec in range(self.total_time):
time.sleep(60)
self.track.set_label()
settimer.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Fri Jul 9 16:49:11 2010
import wx
import timer
# begin wxGlade: extracode
# end wxGlade
class Timer(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: Timer.__init__
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.hours_text = wx.TextCtrl(self, -1, "")
self.hours = wx.StaticText(self, -1, "HH")
self.minutes_text = wx.TextCtrl(self, -1, "")
self.minutes = wx.StaticText(self, -1, "MM")
self.set = wx.Button(self, -1, "Set")
self.out_instance = None
self.__set_properties()
self.__do_layout()
self.Bind(wx.EVT_BUTTON, self.on_set, self.set)
# end wxGlade
def __set_properties(self):
# begin wxGlade: Timer.__set_properties
self.SetTitle("Set Timer")
self.hours_text.SetMinSize((40, 25))
self.hours.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
self.minutes_text.SetMinSize((40, 25))
self.minutes.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
self.set.SetMinSize((50, 27))
# end wxGlade
def __do_layout(self):
# begin wxGlade: Timer.__do_layout
flex_sizer = wx.FlexGridSizer(1, 5, 0, 4)
flex_sizer.Add(self.hours_text, 0, 0, 0)
flex_sizer.Add(self.hours, 0, wx.ALIGN_CENTER_VERTICAL, 0)
flex_sizer.Add(self.minutes_text, 0, 0, 0)
flex_sizer.Add(self.minutes, 0, wx.ALIGN_CENTER_VERTICAL, 0)
flex_sizer.Add(self.set, 0, wx.ALIGN_CENTER_VERTICAL, 0)
self.SetSizer(flex_sizer)
flex_sizer.Fit(self)
flex_sizer.AddGrowableRow(1)
flex_sizer.AddGrowableCol(3)
self.Layout()
# end wxGlade
def get_out_instance(self, out):
# get the instance of trackwork
# this method is meant to be called outside this class
self.out_instance = out
def on_set(self, event): # wxGlade: Timer.<event_handler>
self.out_instance.hours = int(self.hours_text.GetValue())
self.out_instance.minutes = int(self.minutes_text.GetValue())
self.out_instance.set_label()
t = timer.Timer(self.out_instance.minutes, self.out_instance)
t.start()
self.Destroy()
event.Skip()
# end of class Timer