source: sasview/park-1.2.1/park/wxmonitor.py @ 3570545

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 3570545 was 3570545, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

Adding park Part 2

  • Property mode set to 100644
File size: 7.5 KB
Line 
1# This program is public domain
2"""
3Asynchronous monitoring service for wx applications.
4
5Define a monitor using park.wxmonitor.wxMonitor(panel) where panel is
6the window which will receive the monitor updates.
7
8In panel, be sure to have methods for onMonitorStart(message),
9onMonitorProgress(message), etc., for the kinds of monitor messages
10the application will send.  The catch-all method is onMonitorMessage,
11which by default will print the messages on the console.  If you
12don't catch onMonitorLog messages then the log messages will be
13sent to the standard python logger.
14
15See `park.monitor` for details on the message types.
16
17Example
18=======
19
20The following defines a panel which responds to monitor messages::
21
22    import wx
23
24    class Panel(wx.Panel):
25        def __init__(self, *args, **kw):
26            wx.Panel.__init__(self, *args, **kw)
27            self.text = wx.TextCtrl(self, size=(200,100), style=wx.TE_MULTILINE)
28            self.gauge = wx.Gauge(self, range=100)
29            sizer = wx.BoxSizer(wx.VERTICAL)
30            sizer.Add(self.text, 0, wx.LEFT | wx.EXPAND)
31            sizer.Add(self.gauge, 0, wx.LEFT | wx.EXPAND)
32            self.SetSizer(sizer)
33            self.text.SetValue('starting value')
34        def onMonitorMessage(self, message):
35            self.text.SetValue(str(message))
36        def onMonitorStart(self, message):
37            self.text.SetValue(str(message))
38            self.gauge.SetValue(0)
39        def onMonitorProgress(self, message):
40            self.text.SetValue(str(message))
41            self.gauge.SetValue(int(100*message.complete/message.total))
42        def onMonitorComplete(self, message):
43            self.text.SetValue(str(message))
44            self.gauge.SetValue(100)
45
46We can put this panel in a simple app::
47
48    app = wx.PySimpleApp()
49    frame = wx.Frame(None, -1, 'Test Monitor')
50    panel = Panel(frame)
51    frame.Show()
52
53Next we attach attach the monitor to this panel and feed some messages from
54another thread::
55
56    import time,thread
57    import park.wxmonitor, park.monitor
58    from park.monitor import Start, Progress, Improvement, Complete
59    monitor = park.wxmonitor.wxMonitor(panel)
60    msgs = [Start(), Progress(1,10), Progress(3,10),
61            Improvement('Better!'), Progerss(6,10), Complete('Best!')]:
62    def message_stream(monitor,msgs):
63        time.sleep(1)
64        for message in msgs:
65          monitor.put(message)
66          time.sleep(1)
67    thread.start_new_thread(message_stream, (monitor,msgs))
68    app.MainLoop()
69   
70You should see the progress bar jump from 10% to 30% to 60% then all the way
71to the end.
72"""
73import logging
74import time
75
76import wx
77import wx.lib.newevent
78
79import park.monitor
80
81(MonitorEvent, EVT_MONITOR) = wx.lib.newevent.NewEvent()
82
83# For wx on Mac OS X we need to sleep after posting a message from
84# a thread in order to give the GUI a chance to update itself.
85SLEEP_TIME = 0.01
86class wxMonitor(park.monitor.Monitor):
87    """
88    Attach a job monitor to a panel.
89   
90    The monitor will perform callbacks to onMonitorStart(message),
91    onMonitorProgress(message), etc. if the associated method is
92    defined.  If the type specific method is not defined, then the
93    monitor will call onMonitorMessage(message).  Otherwise the
94    message is dropped.
95   
96    See `park.monitor` for a description of the usual messages.
97    """
98    def __init__(self, win):
99        """
100        Window to receive the monitoring events.  This is running in the
101        GUI thread.
102        """
103        self.win = win
104        win.Bind(EVT_MONITOR, self.dispatch)
105
106    def put(self, message):
107        """
108        Intercept an event received from an asynchronous monitor.  This is
109        running in the asynchronous thread.
110        """
111        #print "dispatch",message
112        event = MonitorEvent(message=message)
113        wx.PostEvent(self.win, event)
114        time.sleep(SLEEP_TIME)
115
116    def dispatch(self, event):
117        """
118        Dispatch the event from the asynchronous monitor.  This is running
119        in the GUI thread.
120        """
121        message = event.message
122        #print "window dispatch",message
123 
124        # First check for a handler in the monitor window
125        fn = getattr(self.win, 'onMonitor'+message.__class__.__name__, None)
126        # If none, then check in our class (we have a default onMonitorLog)
127        if fn is None:
128            fn = getattr(self, 'onMonitor'+message.__class__.__name__, None)
129        # If still none, then look for the generic handler
130        if fn is None:
131            fn = getattr(self.win, 'onMonitorMessage', self.onMonitorMessage)
132        # Process the message
133        fn(message)
134
135    def onMonitorMessage(self, message):
136        """
137        Generic message handler: do nothing.
138        """
139        print ">",str(message)
140
141    def onMonitorLog(self, message):
142        """
143        Called when the job sends a logging record.
144
145        The logging record contains a normal python logging record.
146
147        The default behaviour is to tie into the application logging
148        system using::
149
150            logger = logging.getLogger(message.record.name)
151            logger.handle(message.record)
152
153        Logging levels are set in the job controller.
154        """
155        logging.basicConfig()
156        logger = logging.getLogger(message.record.name)
157        logger.handle(message.record)
158
159
160def demo(rate=0):
161    import thread
162    import time
163    import sys
164    import logging
165   
166    class Panel(wx.Panel):
167        def __init__(self, *args, **kw):
168            wx.Panel.__init__(self, *args, **kw)
169            self.text = wx.TextCtrl(self, size=(200,100), style=wx.TE_MULTILINE)
170            self.gauge = wx.Gauge(self, range=100)
171            sizer = wx.BoxSizer(wx.VERTICAL)
172            sizer.Add(self.text, 0, wx.LEFT | wx.EXPAND)
173            sizer.Add(self.gauge, 0, wx.LEFT | wx.EXPAND)
174            self.SetSizer(sizer)
175            self.text.SetValue('starting value')
176        def onMonitorMessage(self, message):
177            self.text.SetValue(str(message))
178        def onMonitorStart(self, message):
179            self.text.SetValue(str(message))
180            self.gauge.SetValue(0)
181        def onMonitorProgress(self, message):
182            self.text.SetValue(str(message))
183            self.gauge.SetValue(int(100*message.complete/message.total))
184        def onMonitorComplete(self, message):
185            self.text.SetValue(str(message))
186            self.gauge.SetValue(100)
187
188    app = wx.PySimpleApp()
189    frame = wx.Frame(None, -1, 'Test Monitor')
190    panel = Panel(frame)
191    frame.Show()
192    monitor = wxMonitor(panel)
193
194    def messagestream(monitor,rate,stream):
195        for m in stream:
196            time.sleep(rate)
197            monitor.put(m)
198        time.sleep(rate)
199        wx.CallAfter(wx.Exit)
200    R = logging.LogRecord('hi',60,'hello.py',3,'log message',(),None,'here')
201    try: raise Exception('Test exception')
202    except: trace = sys.exc_info()
203    stream=[park.monitor.Start(),
204            park.monitor.Progress(1,10),
205            park.monitor.Progress(2,10),
206            park.monitor.Progress(3,10),
207            park.monitor.Improvement('Better!'),
208            park.monitor.Abort('Abandoned'),
209            park.monitor.Start(),
210            park.monitor.Progress(1,10,'seconds'),
211            park.monitor.Improvement('Better!'),
212            park.monitor.Progress(8,10),
213            park.monitor.Complete('Best!'),
214            park.monitor.Start(),
215            park.monitor.Log(R),
216            park.monitor.Progress(6,10),
217            park.monitor.Error(trace)]
218    thread.start_new_thread(messagestream, (monitor,rate,stream))
219    app.MainLoop()
220
221if __name__  == "__main__": demo(rate=1)
Note: See TracBrowser for help on using the repository browser.