ボタンを押すと特定のプログラムを実行し、実行している間プログレスバーを表示する(その3)

サブプロセスの実行中は、実行していることを示すプログレスバーを表示し、実行が終了したらプログレスバーを消すようなコードを作りたい。

過去、d:id:Megumi221:20070730(その1)、d:id:Megumi221:20070731(その2)では、プログレスバーを単独で表示する方法のみ検討していた。サブプロセスの実行方法は、別のところ(d:id:Megumi221:20071005 d:id:Megumi221:20070820)で検討しているので、今回はこれら二つを組み合わせて動かす方法を具体的に考える。

書いたコードは以下の通り。

""" progbar.py """
import wx
import sys
import time, subprocess

class NewFrame(wx.Frame):
    """ gauge frame: this frame will be closed when the process
        is completed.  """
    
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, -1, "gauge", size=(200,100))
        panel = wx.Panel(self)
        panel.SetBackgroundColour('YELLOW')
        
        self.StTxt0 = wx.StaticText(panel, -1, "Process is now running...")
        self.g1 = wx.Gauge(panel, -1, 10)
        self.Bind(wx.EVT_TIMER, self.TimerHandler)
        self.timer = wx.Timer(self)
        self.timer.Start(50)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.StTxt0, 0, wx.ALIGN_CENTER)
        sizer.Add(self.g1, 0, wx.ALIGN_CENTER|wx.EXPAND)
        panel.SetSizer(sizer)

    def TimerHandler(self, event):
        self.g1.Pulse()
        
class MyFrame(wx.Frame):
    """ main frame: "Run" button is put on this frame
        when you push the button, gauge frame appears
        while a process is running. """
    
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Push button!", size=(200,120))
        Pan = wx.ScrolledWindow(self, -1)
        Pan.SetScrollRate(10,10)
        
        Btn1 = wx.Button(Pan, -1, "Run")
        Btn1.Bind(wx.EVT_BUTTON, self.OnRun)               
        self.Show()
       
    def OnRun(self, event):
        self.gauge = NewFrame(self)
        self.gauge.Show(True)   #<--- プログレスバーを表示する
        
        ### process starts    #<--- サブプロセスを実行する
        cmd = "python cmdtest.py"
        p=subprocess.Popen(cmd, stdout=subprocess.PIPE)
        itime = 0
        while (p.poll()==None):
            itime +=1
            time.sleep(0.2)
        ### process ends     #<--- サブプロセスを終了する

        self.gauge.Destroy()   #<--- プログレスバーを消す

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame()
        return True

app = MyApp()
app.MainLoop()

上のコード中、cmd="python cmdtest.py"のところで指定しているcmdtest.pyの内容は、ある程度の時間動いていれば役目は果たせるので、例えば、

""" cmdtest.py """
import string
import time

time.sleep(10)

とする。

実行は、以下で行う。

% python progbar.py

このコードだと、上の画像の”現実”のようにプロセス実行中はプログレスバーがうまく表示できていない。サブプロセス部分をすべてコメントアウトしてプログレスバーの表示だけをさせると、上の画像の”理想”の通りに表示することができる。つまり、今の"progbar.py"では、プログレスバーの表示がサブプロセス部分の影響を受けておかしくなっている。
今後、解決方法を検討する。