]>
Commit | Line | Data |
---|---|---|
1 | # 11/20/2003 - Jeff Grimmett (grimmtooth@softhome.net) | |
2 | # | |
3 | # o Updated for wx namespace | |
4 | # | |
5 | ||
6 | import wx | |
7 | ||
8 | #---------------------------------------------------------------------- | |
9 | ||
10 | class TestPanel(wx.Panel): | |
11 | def __init__(self, parent, ID, log): | |
12 | wx.Panel.__init__(self, parent, ID) | |
13 | self.log = log | |
14 | ||
15 | self.process = None | |
16 | self.Bind(wx.EVT_IDLE, self.OnIdle) | |
17 | ||
18 | # We can either derive from wxProcess and override OnTerminate | |
19 | # or we can let wxProcess send this window an event that is | |
20 | # caught in the normal way... | |
21 | self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded) | |
22 | ||
23 | ||
24 | # Make the controls | |
25 | prompt = wx.StaticText(self, -1, 'Command line:') | |
26 | self.cmd = wx.TextCtrl(self, -1, 'python -u data/echo.py') | |
27 | self.exBtn = wx.Button(self, -1, 'Execute') | |
28 | ||
29 | self.out = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE|wx.TE_READONLY) | |
30 | ||
31 | self.inp = wx.TextCtrl(self, -1, '', style=wx.TE_PROCESS_ENTER) | |
32 | self.sndBtn = wx.Button(self, -1, 'Send') | |
33 | self.termBtn = wx.Button(self, -1, 'Close Stream') | |
34 | self.inp.Enable(False) | |
35 | self.sndBtn.Enable(False) | |
36 | self.termBtn.Enable(False) | |
37 | ||
38 | # Hook up the events | |
39 | self.Bind(wx.EVT_BUTTON, self.OnExecuteBtn, self.exBtn) | |
40 | self.Bind(wx.EVT_BUTTON, self.OnSendText, self.sndBtn) | |
41 | self.Bind(wx.EVT_BUTTON, self.OnCloseStream, self.termBtn) | |
42 | self.Bind(wx.EVT_TEXT_ENTER, self.OnSendText, self.inp) | |
43 | ||
44 | ||
45 | # Do the layout | |
46 | box1 = wx.BoxSizer(wx.HORIZONTAL) | |
47 | box1.Add(prompt, 0, wx.ALIGN_CENTER) | |
48 | box1.Add(self.cmd, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 5) | |
49 | box1.Add(self.exBtn, 0) | |
50 | ||
51 | box2 = wx.BoxSizer(wx.HORIZONTAL) | |
52 | box2.Add(self.inp, 1, wx.ALIGN_CENTER) | |
53 | box2.Add(self.sndBtn, 0, wx.LEFT, 5) | |
54 | box2.Add(self.termBtn, 0, wx.LEFT, 5) | |
55 | ||
56 | sizer = wx.BoxSizer(wx.VERTICAL) | |
57 | sizer.Add(box1, 0, wx.EXPAND|wx.ALL, 10) | |
58 | sizer.Add(self.out, 1, wx.EXPAND|wx.ALL, 10) | |
59 | sizer.Add(box2, 0, wx.EXPAND|wx.ALL, 10) | |
60 | ||
61 | self.SetSizer(sizer) | |
62 | self.SetAutoLayout(True) | |
63 | ||
64 | ||
65 | def __del__(self): | |
66 | if self.process is not None: | |
67 | self.process.Detach() | |
68 | self.process.CloseOutput() | |
69 | self.process = None | |
70 | ||
71 | ||
72 | def OnExecuteBtn(self, evt): | |
73 | cmd = self.cmd.GetValue() | |
74 | ||
75 | self.process = wx.Process(self) | |
76 | self.process.Redirect(); | |
77 | pid = wx.Execute(cmd, wx.EXEC_ASYNC, self.process) | |
78 | self.log.write('OnExecuteBtn: "%s" pid: %s\n' % (cmd, pid)) | |
79 | ||
80 | self.inp.Enable(True) | |
81 | self.sndBtn.Enable(True) | |
82 | self.termBtn.Enable(True) | |
83 | self.cmd.Enable(False) | |
84 | self.exBtn.Enable(False) | |
85 | self.inp.SetFocus() | |
86 | ||
87 | ||
88 | def OnSendText(self, evt): | |
89 | text = self.inp.GetValue() | |
90 | self.inp.SetValue('') | |
91 | self.log.write('OnSendText: "%s"\n' % text) | |
92 | self.process.GetOutputStream().write(text + '\n') | |
93 | self.inp.SetFocus() | |
94 | ||
95 | ||
96 | def OnCloseStream(self, evt): | |
97 | self.log.write('OnCloseStream\n') | |
98 | #print "b4 CloseOutput" | |
99 | self.process.CloseOutput() | |
100 | #print "after CloseOutput" | |
101 | ||
102 | def OnIdle(self, evt): | |
103 | if self.process is not None: | |
104 | stream = self.process.GetInputStream() | |
105 | ||
106 | if stream.CanRead(): | |
107 | text = stream.read() | |
108 | self.out.AppendText(text) | |
109 | ||
110 | ||
111 | def OnProcessEnded(self, evt): | |
112 | self.log.write('OnProcessEnded, pid:%s, exitCode: %s\n' % | |
113 | (evt.GetPid(), evt.GetExitCode())) | |
114 | ||
115 | stream = self.process.GetInputStream() | |
116 | ||
117 | if stream.CanRead(): | |
118 | text = stream.read() | |
119 | self.out.AppendText(text) | |
120 | ||
121 | self.process.Destroy() | |
122 | self.process = None | |
123 | self.inp.Enable(False) | |
124 | self.sndBtn.Enable(False) | |
125 | self.termBtn.Enable(False) | |
126 | self.cmd.Enable(True) | |
127 | self.exBtn.Enable(True) | |
128 | ||
129 | ||
130 | #---------------------------------------------------------------------- | |
131 | ||
132 | def runTest(frame, nb, log): | |
133 | win = TestPanel(nb, -1, log) | |
134 | return win | |
135 | ||
136 | ||
137 | #---------------------------------------------------------------------- | |
138 | ||
139 | ||
140 | overview = """\ | |
141 | <html><body> | |
142 | <h2>wxProcess</h2> | |
143 | ||
144 | wxProcess lets you get notified when an asyncronous child process | |
145 | started by wxExecute terminates, and also to get input/output streams | |
146 | for the child process's stdout, stderr and stdin. | |
147 | ||
148 | <p> | |
149 | This demo launches a simple python script that echos back on stdout | |
150 | lines that it reads from stdin. You can send text to the echo | |
151 | process' stdin by typing in the lower textctrl and clicking Send. | |
152 | ||
153 | <p> | |
154 | Clicking the Close Stream button will close the demo's end of the | |
155 | stdin pipe to the child process. In our case that will cause the | |
156 | child process to exit its main loop. | |
157 | ||
158 | </body><html> | |
159 | """ | |
160 | ||
161 | ||
162 | if __name__ == '__main__': | |
163 | import sys,os | |
164 | import run | |
165 | run.main(['', os.path.basename(sys.argv[0])]) |