用户在运行一个 Python GUI 应用时,遇到了 Pango 错误,该错误通常出现在程序运行一分钟后。以下是该用户提供的代码片段:
#!/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
2、解决方案
该错误通常是由多线程问题引起的,解决方法是将计时器线程与 GUI 线程分开,让计时器线程独立运行。以下是修改后的代码片段:
#!/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
from threading import Thread
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)
def on_set1(self, event): # wxGlade: MyFrame.<event_handler>
self.timer_thread = TimerThread(self, self.minutes)
self.timer_thread.start()
event.Skip()
def set_label(self):
self.timer_label1.SetLabel("%02d:%02d" % (self.hours, self.minutes))
self.minutes -= 1
class TimerThread(Thread):
def __init__(self, track, minutes):
Thread.__init__(self)
self.track = track
self.minutes = minutes
def run(self):
for sec in range(self.minutes):
time.sleep(60)
self.track.set_label()
# 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()
在修改后的代码中,计时器线程被移出了 GUI 类,并作为单独的线程运行。这样,计时器线程就不会与 GUI 线程冲突,Pango 错误也不会再出现了。