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 [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]