2011-07-10 16 views
0

これは私のジャムです。私はPythonにSUPER NEW(すなわちdays)を使用しています。常に実行している一連のpythonスクリプトのGUI上でかなり良い進歩を遂げました。基本的に私の音楽コレクションのデータベースを構築します。私はコマンドラインでそれを実行すると、それは恒星の仕事を行います。私はそれがPythonを学ぶのに最適な方法だと考えています - このことのフロントエンドを構築してください。wxPython:マルチスレッドヘルプ

したがって、以下は実際に私のために働いています。私はスキャンが動作するようになっている間、スキャン/アップデートボタンが「ダウン」状態のままになるときに問題に遭遇しました。私は、はい、私は、STDOUTからのself.LogViewに出力を得るために、これをマルチスレッドする必要があることを学んだ。それも機能します。リアルタイムではありません。私はそれについて以前に投稿し、ウェブ上の別のチュートリアルにリンクしていましたが、これを過ぎていないだけで、必死になっています。親愛なるStackflow.com - 私を狂人から救ってください。以下の作業を行うことができれば、チュートリアルが過度に簡素化され、少なくとも私の頭の中に入っているので、少なくともあなたが行ったことをリバースエンジニアリングすることができます。 DEFボタンで

    proc = subprocess.Popen([scanCMD],shell=True,stdout=subprocess.PIPE) 
       for line in proc.stdout: 
        wx.CallAfter(self.LogWindow.AppendText(line)) 

:ザ・はそれは以下に力仕事である

はこれです

def bt_ScanUpdateClick(self, event): 

チョウは私が

#!/usr/bin/python 
################################################################################ 
# myGUI 
################################################################################ 
# THIS WORKS, BUT DOES NOT MULTITHREAD! 
################################################################################ 

import wx 
from wxPython.wx import * 
import os 
import subprocess 
import threading 

class myGUI(wx.Frame): 

    def __init__(self, parent, title): 
     super(myGUI, self).__init__(parent, title=title, 
      size=(450, 245)) #360 for logwindow (see below) 
     panel = wx.Panel(self) 
     sizer = wx.GridBagSizer(6, 5) 
     self.currentDirectory = os.getcwd() 

    # [0] Main Database Text, Entry and Browse Button -------------------------- 
     label_MainDatabase = wx.StaticText(panel, label="Database:") 
     sizer.Add(label_MainDatabase, pos=(0, 0), flag=wx.LEFT| 
      wx.ALIGN_CENTER_VERTICAL, border=10) 

     self.tc_MainDatabase = wx.TextCtrl(panel) 
     sizer.Add(self.tc_MainDatabase, pos=(0, 1), span=(1, 4), flag=wx.TOP| 
      wx.EXPAND|wx.ALIGN_CENTER_VERTICAL) 

     bt_MainDatabase = wx.Button(panel, label="Browse...") 
     sizer.Add(bt_MainDatabase, pos=(0, 5), flag=wx.LEFT|wx.RIGHT| 
      wx.ALIGN_CENTER_VERTICAL, border=10) 
     bt_MainDatabase.Bind(wx.EVT_BUTTON, self.bt_MainDatabaseClick, 
      bt_MainDatabase) 
    # -------------------------------------------------------------------------- 
    # [1] Paths to scan for new Music ------------------------------------------ 
     self.sb_FoldersToScan = wx.StaticBox(panel, label="Folders to Scan:", size=(200,100)) 
     folderBoxSizer = wx.StaticBoxSizer(self.sb_FoldersToScan, wx.VERTICAL) 
     self.multiText = wx.TextCtrl(panel, -1,"",size=(300, 100), style=wx.TE_MULTILINE|wx.TE_READONLY) 
     self.multiText.SetInsertionPoint(0) 
     folderBoxSizer.Add(self.multiText, flag=wx.EXPAND) 
     sizer.Add(folderBoxSizer, pos=(1, 0), span=(1, 6), flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.RIGHT, border=10) 
     bt_FoldersToScanAdd = wx.Button(panel, label="Add") 
     bt_FoldersToScanClear = wx.Button(panel, label="Clear") 
    # -------------------------------------------------------------------------- 
    # [2] Buttons to Add Folder, Clear Scan Area ------------------------------- 
     sizer.Add(bt_FoldersToScanAdd, pos=(2,0), span=(1,2), flag=wx.LEFT|wx.RIGHT| 
      wx.ALIGN_CENTER_VERTICAL, border=10) 
     bt_FoldersToScanAdd.Bind(wx.EVT_BUTTON, self.bt_FoldersToScanAddClick, bt_FoldersToScanAdd) 
     sizer.Add(bt_FoldersToScanClear, pos=(2,5), flag=wx.LEFT|wx.RIGHT| 
      wx.ALIGN_CENTER_VERTICAL, border=10) 
     bt_FoldersToScanClear.Bind(wx.EVT_BUTTON, self.bt_FoldersToScanClearClick, bt_FoldersToScanClear) 
    # -------------------------------------------------------------------------- 
    # [3] Separator line ------------------------------------------------------- 
     hl_SepLine1 = wx.StaticLine(panel, 0, (250, 50), (300,1)) 
     sizer.Add(hl_SepLine1, pos=(3, 0), span=(1, 6), flag=wx.EXPAND, border=10) 
    # -------------------------------------------------------------------------- 
    # [4] Add Scan Options and Scan Button ------------------------------------- 
     bt_ScanUpdate = wx.Button(panel, label="Scan/Update") 
     bt_ScanUpdate.Bind(wx.EVT_BUTTON, self.bt_ScanUpdateClick, bt_ScanUpdate) 
     bt_ScanRepair = wx.Button(panel, label="Repair") 
     bt_ScanRepair.Bind(wx.EVT_BUTTON, self.bt_ScanRepairClick, bt_ScanRepair) 
     self.ck_ScanVerbose = wx.CheckBox(panel, label="Verbose") 
     self.ck_ScanLog = wx.CheckBox(panel, label="Log") 
     sizer.Add(bt_ScanUpdate, pos=(4,0), span=(1,2), flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, border=10) 
     sizer.Add(self.ck_ScanVerbose, pos=(4,2), flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, border=10) 
     sizer.Add(self.ck_ScanLog, pos=(4,4), flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, border=10) 
     sizer.Add(bt_ScanRepair, pos=(4,5), span=(1,2), flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, border=10) 
    # -------------------------------------------------------------------------- 
    # [5] Separator line ------------------------------------------------------ 
     hl_SepLine2 = wx.StaticLine(panel, 0, (250, 50), (300,1)) 
     sizer.Add(hl_SepLine2, pos=(5, 0), span=(1, 6), flag=wx.EXPAND, border=10) 
    # -------------------------------------------------------------------------- 
    # [6] Output/Log Box ------------------------------------------------------- 
     self.LogWindow = wx.TextCtrl(panel, -1,"",size=(100, 100), style=wx.TE_MULTILINE|wx.TE_READONLY) 
     self.LogWindow.SetInsertionPoint(0) 
     sizer.Add(self.LogWindow, pos=(6,0), span=(1,6), flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL, border=10) 

    # DEBUG 
     self.multiText.Value = "~/Network/Pictures/Test" 

     sizer.AddGrowableCol(2) 
     panel.SetSizer(sizer) 

     self.Centre() 
     self.Show() 

    def bt_MainDatabaseClick(self, event): 
     # Create a list of filters 
     filters = 'All files (*.*)|*.*|Text files (*.db)|*.db' 
     dialog = wxFileDialog (None, message = 'Select Database File...', 
      wildcard = filters, style = wxOPEN) 

     # Open Dialog Box and get Selection 
     if dialog.ShowModal() == wxID_OK: 
      selected = dialog.GetFilenames() 
      for selection in selected: 
       self.tc_MainDatabase.Value = selection 
     dialog.Destroy() 

    def bt_FoldersToScanAddClick(self, event): 
     dialog = wx.DirDialog(self, "Add a Directory...", style=wx.DD_DEFAULT_STYLE) 

     if dialog.ShowModal() == wx.ID_OK: 
      self.multiText.Value += "%s" % dialog.GetPath() + "\n" 
     dialog.Destroy() 

    def bt_FoldersToScanClearClick(self, event): 
     self.multiText.Value = "" 

    def bt_ScanUpdateClick(self, event): 
     self.SetSizeWH(450,360) 
     thread = threading.Thread() 
     thread.setDaemon(True) 
     thread.start() 

     ## DEBUG 
     self.tc_MainDatabase.Value = "test.db" 

     if self.tc_MainDatabase.Value == "": 
      self.LogWindow.Value += "ERROR:\tNo database name selected!\n" 
     else: 
      scanCMD = "./scan -d " + self.tc_MainDatabase.Value + " " 

      numLines=0 
      maxLines=(int(self.multiText.GetNumberOfLines())) 

      if self.multiText.GetLineText(numLines) == "": 
       self.LogWindow.Value += "ERROR\tNo folder selected to scan!\n" 
      else: 
       self.LogWindow.Value += "Running Scan...\n\n" 
       while (numLines < maxLines): 
        scanCMD += str(self.multiText.GetLineText(numLines)) + " " 
        numLines += 1 

       self.LogWindow.Value += scanCMD 

       proc = subprocess.Popen([scanCMD],shell=True,stdout=subprocess.PIPE) 
       for line in proc.stdout: 
        wx.CallAfter(self.LogWindow.AppendText(line)) 

#    p = subprocess.Popen([scanCMD],shell=True,stdout=subprocess.PIPE) 
#    self.LogWindow.Value += p.stdout.readline() 

    def bt_ScanRepairClick(self, event): 
     print "Repair clicked" 

if __name__ == '__main__': 
    app = wx.App() 
    myGUI(None, title="myGUI") 

    app.MainLoop() 

答えて

0

ひょうメアリーを投げつけます以前は自分のスレッドをデーモンに設定する必要はありませんでした。実際、私はスレッドをサブクラス化しただけです。私はスレッド化の専門家ではないので、http://wiki.wxpython.org/LongRunningTasksを見てそこのメソッドの1つを試してみるか、私がここで使った方法論を使ってみることをお勧めします:http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/私は後者を何度も問題なく使用しました。それ以外の場合は、公式のwxPythonユーザーのグループにクロスポストする必要があります。このグループには非常に知識のある人がいます。

+0

私はそれが働いていると思う - ありがとうマイク。 :)今は、スレッドでうまくいくようにSTDOUTを取得することはできませんが、スレッド*が動作しているようです。 – chow