these are the sources I am using and that show this problem in various versions of Linux.
--- program-wx.py (the entry point) --- #!/usr/bin/python2.6 # -*- coding: utf-8 -*- #*********************************************************************** #* #*********************************************************************** #* Project : various #* #* $Id: asc.py 7726 2009-08-17 09:44:05Z Mario $ #* #* initial programmer : Mario Frasca #* initial date : 20090819 #********************************************************************** __revision__ = "$Rev: 7726 $"[6:-2] import wx, os, program_wxglade, logging, threading import the_program import nens.swx log = logging.getLogger('nens.lcm.wx') log.setLevel(logging.DEBUG) class RunningDialog(program_wxglade.RunningDialog): def __init__(self, *args, **kwargs): program_wxglade.RunningDialog.__init__(self, *args, **kwargs) self.handler = nens.swx.TextCtrlHandler(self.text_ctrl_logging, level=logging.DEBUG) logging.getLogger('').addHandler(self.handler) self.count = 0 def OnIdle(self, event): self.gauge.Pulse() pass def OnThreadStart(self, thread): self.handler.ClearWindow() log.debug('starting LCM - binding events') for i in [self.GetParent().button_configure, self.GetParent().button_defaults, self.GetParent().button_run]: i.Disable() pass def OnThreadEnd(self, thread): log.debug('LCM ended - unbinding events') self.gauge.SetValue(0) for i in [self.GetParent().button_configure, self.GetParent().button_defaults, self.GetParent().button_run]: i.Enable() class ClosableWindow: def __init__(self, *argv, **kwargs): self.button_close.Bind(wx.EVT_BUTTON, self.onExit) def onExit(self, event): self.Close(True) # Close this frame. class LCMDialog(program_wxglade.LCMDialog, ClosableWindow): def __init__(self, *argv, **kwargs): program_wxglade.LCMDialog.__init__(self, *argv, **kwargs) ClosableWindow.__init__(self, *argv, **kwargs) self.button_run.Bind(wx.EVT_BUTTON, self.OnRun) self.running_dialog = RunningDialog(parent=self) def OnRun(self, event): self.running_dialog.Show() mainThread = nens.swx.MainThread( dialog = self.running_dialog, target = the_program.main, args = (None, [self.text_ctrl_name_configuration.GetValue()]) ) mainThread.start() def chooseConfiguration(self, event): dialog = wx.FileDialog(self, message="choose configuration file", defaultDir=os.getcwd(), wildcard="Windows *.ini|*.ini|All files (*.*)|*.*") if dialog.ShowModal() == wx.ID_OK: self.text_ctrl_name_configuration.SetValue(dialog.GetPath()) dialog.Destroy() def onExit(self, event): self.Close(True) # Close this frame. exit() # and exit class ConfigDialog(program_wxglade.ConfigDialog, ClosableWindow): pass class DefaultsDialog(program_wxglade.DefaultsDialog): pass if __name__ == "__main__": import gettext gettext.install("app") # replace with the appropriate catalog name app = wx.PySimpleApp(0) wx.InitAllImageHandlers() program_dialog = LCMDialog(None, -1, "") app.SetTopWindow(program_dialog) program_dialog.Show() app.MainLoop() --- end --- --- program_wxglade.py (the interface) --- #!/usr/bin/env python # -*- coding: utf-8 -*- # generated by wxGlade 0.6.3 on Tue Aug 25 10:57:18 2009 import wx import wx.grid # begin wxGlade: extracode # end wxGlade class LCMDialog(wx.Dialog): def __init__(self, *args, **kwds): # begin wxGlade: LCMDialog.__init__ kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME wx.Dialog.__init__(self, *args, **kwds) self.vbox_33_copy_staticbox = wx.StaticBox(self, -1, _("current configuration file")) self.button_configure = wx.Button(self, -1, _("configure")) self.button_defaults = wx.Button(self, -1, _("defaults")) self.button_new_actions = wx.Button(self, -1, _("new actions")) self.button_run = wx.Button(self, -1, _("run")) self.button_close = wx.Button(self, -1, _("close")) self.text_ctrl_name_configuration = wx.TextCtrl(self, -1, "") self.button_choose = wx.Button(self, -1, _("...")) self.label_1 = wx.StaticText(self, -1, _("last log and next run hints")) self.text_ctrl_2 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.HSCROLL) self.text_ctrl_3 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.HSCROLL) self.label_2 = wx.StaticText(self, -1, _("idle")) self.__set_properties() self.__do_layout() # end wxGlade def __set_properties(self): # begin wxGlade: LCMDialog.__set_properties self.SetTitle(_("LCM : Lizard Configuration Manager")) self.SetSize((534, 370)) self.text_ctrl_name_configuration.SetMinSize((0, 24)) self.button_choose.SetMinSize((24, 24)) self.label_2.Enable(False) # end wxGlade def __do_layout(self): # begin wxGlade: LCMDialog.__do_layout sizer_1 = wx.BoxSizer(wx.VERTICAL) sizer_3 = wx.BoxSizer(wx.HORIZONTAL) vbox_33_copy = wx.StaticBoxSizer(self.vbox_33_copy_staticbox, wx.VERTICAL) hbox_311_copy = wx.BoxSizer(wx.HORIZONTAL) sizer_2 = wx.BoxSizer(wx.HORIZONTAL) sizer_2.Add(self.button_configure, 0, 0, 0) sizer_2.Add((10, 20), 0, wx.EXPAND, 0) sizer_2.Add(self.button_defaults, 0, 0, 0) sizer_2.Add((10, 20), 0, wx.EXPAND, 0) sizer_2.Add(self.button_new_actions, 0, 0, 0) sizer_2.Add((10, 20), 0, wx.EXPAND, 0) sizer_2.Add(self.button_run, 0, 0, 0) sizer_2.Add((20, 20), 1, wx.EXPAND, 0) sizer_2.Add(self.button_close, 0, 0, 0) sizer_1.Add(sizer_2, 0, wx.EXPAND, 0) hbox_311_copy.Add(self.text_ctrl_name_configuration, 3, 0, 0) hbox_311_copy.Add(self.button_choose, 0, 0, 0) vbox_33_copy.Add(hbox_311_copy, 0, wx.EXPAND, 0) sizer_1.Add(vbox_33_copy, 0, wx.EXPAND, 0) sizer_1.Add(self.label_1, 0, 0, 0) sizer_3.Add(self.text_ctrl_2, 2, wx.EXPAND, 0) sizer_3.Add(self.text_ctrl_3, 1, wx.EXPAND, 0) sizer_1.Add(sizer_3, 1, wx.EXPAND, 0) sizer_1.Add(self.label_2, 0, wx.ALL, 2) self.SetSizer(sizer_1) self.Layout() # end wxGlade # end of class LCMDialog class ConfigDialog(wx.Dialog): def __init__(self, *args, **kwds): # begin wxGlade: ConfigDialog.__init__ kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME wx.Dialog.__init__(self, *args, **kwds) self.vbox_33_staticbox = wx.StaticBox(self, -1, _("other settings")) self.vbox_23_staticbox = wx.StaticBox(self, -1, _("base directories")) self.button_revert = wx.Button(self, -1, _("revert")) self.button_save = wx.Button(self, -1, _("save")) self.button_close = wx.Button(self, -1, _("close")) self.label_configuration = wx.StaticText(self, -1, _("configuration")) self.text_ctrl_configuration = wx.TextCtrl(self, -1, "") self.button_configuration_choose = wx.Button(self, -1, _("...")) self.label_locations = wx.StaticText(self, -1, _("locations")) self.text_ctrl_locations = wx.TextCtrl(self, -1, "") self.button_locations_choose = wx.Button(self, -1, _("...")) self.label_lp_pairs = wx.StaticText(self, -1, _("lp pairs")) self.text_ctrl_lp_pairs = wx.TextCtrl(self, -1, "") self.button_lp_pairs_choose = wx.Button(self, -1, _("...")) self.label_output = wx.StaticText(self, -1, _("output")) self.text_ctrl_output = wx.TextCtrl(self, -1, "") self.button_output_choose = wx.Button(self, -1, _("...")) self.label_status_dir = wx.StaticText(self, -1, _("status dir")) self.text_ctrl_status_dir = wx.TextCtrl(self, -1, "") self.button_status_dir_choose = wx.Button(self, -1, _("...")) self.label_loglevel = wx.StaticText(self, -1, _("logging level")) self.choice_loglevel = wx.Choice(self, -1, choices=[_("NOTSET"), _("DEBUG"), _("INFO"), _("WARNING"), _("ERROR")]) self.__set_properties() self.__do_layout() # end wxGlade def __set_properties(self): # begin wxGlade: ConfigDialog.__set_properties self.SetTitle(_("config.ini editor")) self.label_configuration.SetMinSize((90, 16)) self.text_ctrl_configuration.SetMinSize((0, 24)) self.button_configuration_choose.SetMinSize((24, 24)) self.label_locations.SetMinSize((90, 16)) self.text_ctrl_locations.SetMinSize((0, 24)) self.button_locations_choose.SetMinSize((24, 24)) self.label_lp_pairs.SetMinSize((90, 16)) self.text_ctrl_lp_pairs.SetMinSize((0, 24)) self.button_lp_pairs_choose.SetMinSize((24, 24)) self.label_output.SetMinSize((90, 16)) self.text_ctrl_output.SetMinSize((0, 24)) self.button_output_choose.SetMinSize((24, 24)) self.label_status_dir.SetMinSize((90, 16)) self.text_ctrl_status_dir.SetMinSize((0, 24)) self.button_status_dir_choose.SetMinSize((24, 24)) self.label_loglevel.SetMinSize((90, 16)) self.choice_loglevel.SetSelection(0) # end wxGlade def __do_layout(self): # begin wxGlade: ConfigDialog.__do_layout vbox = wx.BoxSizer(wx.VERTICAL) vbox_33 = wx.StaticBoxSizer(self.vbox_33_staticbox, wx.VERTICAL) hbox_311 = wx.BoxSizer(wx.HORIZONTAL) vbox_23 = wx.StaticBoxSizer(self.vbox_23_staticbox, wx.VERTICAL) hbox_255 = wx.BoxSizer(wx.HORIZONTAL) hbox_245 = wx.BoxSizer(wx.HORIZONTAL) hbox_235 = wx.BoxSizer(wx.HORIZONTAL) hbox_225 = wx.BoxSizer(wx.HORIZONTAL) hbox_215 = wx.BoxSizer(wx.HORIZONTAL) hbox_13 = wx.BoxSizer(wx.HORIZONTAL) hbox_13.Add(self.button_revert, 0, 0, 0) hbox_13.Add((10, 20), 0, wx.EXPAND, 0) hbox_13.Add(self.button_save, 0, 0, 0) hbox_13.Add((20, 20), 1, wx.EXPAND, 0) hbox_13.Add(self.button_close, 0, 0, 0) vbox.Add(hbox_13, 0, wx.EXPAND, 0) hbox_215.Add(self.label_configuration, 0, 0, 0) hbox_215.Add(self.text_ctrl_configuration, 3, 0, 0) hbox_215.Add(self.button_configuration_choose, 0, 0, 0) vbox_23.Add(hbox_215, 0, wx.EXPAND, 0) hbox_225.Add(self.label_locations, 0, 0, 0) hbox_225.Add(self.text_ctrl_locations, 3, 0, 0) hbox_225.Add(self.button_locations_choose, 0, 0, 0) vbox_23.Add(hbox_225, 0, wx.EXPAND, 0) hbox_235.Add(self.label_lp_pairs, 0, 0, 0) hbox_235.Add(self.text_ctrl_lp_pairs, 3, 0, 0) hbox_235.Add(self.button_lp_pairs_choose, 0, 0, 0) vbox_23.Add(hbox_235, 0, wx.EXPAND, 0) hbox_245.Add(self.label_output, 0, 0, 0) hbox_245.Add(self.text_ctrl_output, 3, 0, 0) hbox_245.Add(self.button_output_choose, 0, 0, 0) vbox_23.Add(hbox_245, 0, wx.EXPAND, 0) hbox_255.Add(self.label_status_dir, 0, 0, 0) hbox_255.Add(self.text_ctrl_status_dir, 3, 0, 0) hbox_255.Add(self.button_status_dir_choose, 0, 0, 0) vbox_23.Add(hbox_255, 0, wx.EXPAND, 0) vbox.Add(vbox_23, 0, wx.EXPAND, 0) hbox_311.Add(self.label_loglevel, 0, 0, 0) hbox_311.Add(self.choice_loglevel, 1, wx.EXPAND, 0) vbox_33.Add(hbox_311, 0, wx.EXPAND, 0) vbox.Add(vbox_33, 1, wx.EXPAND, 0) self.SetSizer(vbox) vbox.Fit(self) self.Layout() # end wxGlade # end of class ConfigDialog class DefaultsDialog(wx.Dialog): def __init__(self, *args, **kwds): # begin wxGlade: DefaultsDialog.__init__ kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME wx.Dialog.__init__(self, *args, **kwds) self.grid_1 = wx.grid.Grid(self, -1, size=(1, 1)) self.__set_properties() self.__do_layout() # end wxGlade def __set_properties(self): # begin wxGlade: DefaultsDialog.__set_properties self.SetTitle(_("defaults editor")) self.SetSize((544, 255)) self.grid_1.CreateGrid(1, 3) self.grid_1.EnableGridLines(0) self.grid_1.EnableDragColSize(0) self.grid_1.EnableDragRowSize(0) self.grid_1.SetSelectionMode(wx.grid.Grid.wxGridSelectRows) self.grid_1.SetColLabelValue(0, _("par. id")) self.grid_1.SetColSize(0, 4) self.grid_1.SetColLabelValue(1, _("softmax")) self.grid_1.SetColLabelValue(2, _("softmin")) # end wxGlade def __do_layout(self): # begin wxGlade: DefaultsDialog.__do_layout sizer_8 = wx.BoxSizer(wx.HORIZONTAL) sizer_8.Add(self.grid_1, 1, wx.EXPAND, 0) self.SetSizer(sizer_8) self.Layout() # end wxGlade # end of class DefaultsDialog class RunningDialog(wx.Dialog): def __init__(self, *args, **kwds): # begin wxGlade: RunningDialog.__init__ kwds["style"] = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.THICK_FRAME wx.Dialog.__init__(self, *args, **kwds) self.text_ctrl_logging = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL|wx.TE_RICH) self.gauge = wx.Gauge(self, -1, 250) self.__set_properties() self.__do_layout() # end wxGlade def __set_properties(self): # begin wxGlade: RunningDialog.__set_properties self.SetTitle(_("console")) self.SetSize((600, 300)) # end wxGlade def __do_layout(self): # begin wxGlade: RunningDialog.__do_layout sizer_4 = wx.BoxSizer(wx.VERTICAL) sizer_4.Add(self.text_ctrl_logging, 1, wx.EXPAND, 0) sizer_4.Add(self.gauge, 0, wx.EXPAND, 0) self.SetSizer(sizer_4) self.Layout() # end wxGlade # end of class RunningDialog if __name__ == "__main__": import gettext gettext.install("app") # replace with the appropriate catalog name app = wx.PySimpleApp(0) wx.InitAllImageHandlers() dialog_lcm = LCMDialog(None, -1, "") app.SetTopWindow(dialog_lcm) dialog_lcm.Show() app.MainLoop() --- end --- --- the_program.py --- # just for the sake of testing... def main(options, args): import time for i in range(33): log.warning('this is warning #%d' % i) for j in range(10): log.info('and this is informational message #%d' % j) time.sleep(0.1) --- end --- --- wsx (my library) -- #*********************************************************************** #* Library : for the lazy interface builder #* #* Project : various #* #* $Id: gp.py 7710 2009-08-17 08:14:18Z Mario $ #* #* initial programmer : Mario Frasca #* initial date : 2009-08-20 #********************************************************************** __revision__ = "$Rev: 7710 $"[6:-2] import logging, wx, threading log = logging.getLogger('nens.swx') log.setLevel(logging.INFO) class TextCtrlHandler(logging.Handler): '''emits formatted records to a wx.TextCtrl widget the widget must be... style=wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL|wx.TE_RICH logging records will be gray (DEBUG), black (INFO) or red (WARNING/ERROR). changing the content of the widget once you have given it to this object will crash your program. you may wipe it clean using the ClearWindow method. NB: this object can crash your Linux program ''' def __init__(self, widget, **kwargs): logging.Handler.__init__(self, **kwargs) self.widget = widget self.semaphore = threading.Semaphore() def emit(self, record): if record.levelno >= logging.WARNING: styleForLevel = wx.TextAttr("red") elif record.levelno >= logging.INFO: styleForLevel = wx.TextAttr("black") else: styleForLevel = wx.TextAttr("grey") self.semaphore.acquire() self.widget.SetDefaultStyle(styleForLevel) self.widget.AppendText(self.format(record)) self.widget.AppendText('\n') self.semaphore.release() def ClearWindow(self): "empty the owned widget" self.semaphore.acquire() self.widget.SetValue('') self.semaphore.release() class MainThread(threading.Thread): '''Thread class taking care of disabling/enabling the convert and close buttons... a dialog box may be given and its OnThreadStart and OnThreadEnd methods will be called when the thread is actually run.''' def __init__(self, dialog=None, *args, **kwargs): self.dialog = dialog threading.Thread.__init__(self, *args, **kwargs) def run(self, *args, **kwargs): try: #print "self.dialog.OnThreadStart(self)" self.dialog.OnThreadStart(self) except Exception, e: #print e pass try: #print "threading.Thread.run(self, *args, **kwargs)" threading.Thread.run(self, *args, **kwargs) except: import traceback log.error("a serious error occurred in the main thread (INFO follows)") log.info(traceback.format_exc()) try: #print "self.dialog.OnThreadEnd(self)" self.dialog.OnThreadEnd(self) except Exception, e: #print e pass --- end --- -- Windows: A thirty-two bit extension to a sixteen-bit graphical shell to an eight-bit operating system originally coded for a four-bit microprocessor, sold by a two-bit company that can't stand one bit of competition. -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org