所以 - 這是我的果醬。我在Python中超級新(即幾天),並且在一個我一直運行的一組python腳本的GUI上取得了一些相當不錯的進展。它基本上建立了我的音樂收藏數據庫。當我在命令行運行它時,它的工作非常出色。我認爲這是學習python的好方法 - 爲此構建一個前端。wxPython:多線程幫助
所以 - 下面確實爲我工作。當掃描/更新按鈕在掃描開始工作時將保持「停止」狀態時,我遇到了問題。我瞭解到,是的,我需要多線程才能將STDOUT的輸出傳遞到self.LogView中。這甚至可以工作,但不是實時的。我早些時候發佈了它,並且鏈接到了網絡上的另一個教程,但我只是沒有越過這個並且越來越絕望。親愛的Stackflow.com - 讓我從瘋狂中解脫出來。如果你能做出下面的工作,那麼我可以逆向工程你至少做了什麼,因爲教程過於簡單化了,是的,我頭腦發熱。
的是在下面繁重是這樣的:
proc = subprocess.Popen([scanCMD],shell=True,stdout=subprocess.PIPE)
for line in proc.stdout:
wx.CallAfter(self.LogWindow.AppendText(line))
在按鈕DEF:
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()
想一想我的工作 - 謝謝邁克。 :)現在我無法讓STDOUT在線程中正常工作,但看起來*線程*部分正在工作。 – chow