views:

35

answers:

1

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
A: 

You should have used wx.Timer instead of starting a thread that will be most of the time waiting.

wx.Timer will call your code in the specified interval.

nosklo
hmm, very interesting.. It fixed the problem. thanks!
Rex Reign