wxPython:多线程帮助

时间:2011-07-10 04:53:06

标签: multithreading wxpython

所以 - 这是我的果酱。我是Python的新东西(即几天),并且在GUI上为我一直运行的一组python脚本取得了一些相当不错的进展。它基本上构建了我的音乐收藏数据库。当我在命令行运行它时,它做了一个很棒的工作。我认为这是学习python的好方法 - 为这件事构建一个前端。

所以 - 以下DOES实际上对我有用。当扫描开始工作时,扫描/更新按钮将保持“关闭”状态时遇到问题。我了解到,是的,我需要多线程来获取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):

Chow fling a hail mary

#!/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()

1 个答案:

答案 0 :(得分:0)

我以前从未需要将我的线程设置为守护进程。事实上,我只有子类的Thread。我不是线程专家,因此我建议查看http://wiki.wxpython.org/LongRunningTasks并尝试其中一种方法或使用我在此处使用的方法:http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/我已经多次使用后者而没有任何问题。否则,您应该交叉发布到官方wxPython用户组,其中有一些知识渊博的人,我相信我们可以帮助您。