gpt4 book ai didi

multithreading - wxPython:线程问题

转载 作者:行者123 更新时间:2023-12-03 13:21:54 25 4
gpt4 key购买 nike

我的程序不断扩展。

在MainPanel类的MainProgram方法中,我正在使用其他程序中的某些函数。使用此方法时,GUI会挂起,直到完成为止,我想通过使用此方法的新线程来解决此问题。

这样做时,执行OnRun时出现错误。它说:

Unhandled exception in thread started by <bound method MainPanel.OnIndex of <__main__.MainPanel; proxy of <Swig Object of type 'wxPanel *' at 0x526e238> >>



它认为这与将Som值设置为self.textOutput的OnIndex有关。现在,我该如何解决我的这个小问题?

非常感谢您的帮助! =)
import wx, thread 

ID_EXIT = 110

class MainPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)

self.buttonRun = wx.Button(self, label="Run")
self.buttonRun.Bind(wx.EVT_BUTTON, self.OnRun )
self.buttonExit = wx.Button(self, label="Exit")
self.buttonExit.Bind(wx.EVT_BUTTON, self.OnExit)

self.labelChooseRoot = wx.StaticText(self, label ="Root catalog: ")
self.labelScratchWrk = wx.StaticText(self, label ="Scratch workspace: ")
self.labelMergeFile = wx.StaticText(self, label ="Merge file: ")

self.textChooseRoot = wx.TextCtrl(self, size=(210, -1))
self.textChooseRoot.Bind(wx.EVT_LEFT_UP, self.OnChooseRoot)
self.textScratchWrk = wx.TextCtrl(self, size=(210, -1))
self.textMergeFile = wx.TextCtrl(self, size=(210, -1))
self.textOutput = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY)

self.sizerF = wx.FlexGridSizer(3, 2, 5, 5)
self.sizerF.Add(self.labelChooseRoot) #row 1, col 1
self.sizerF.Add(self.textChooseRoot) #row 1, col 2
self.sizerF.Add(self.labelScratchWrk) #row 2, col 1
self.sizerF.Add(self.textScratchWrk) #row 2, col 2
self.sizerF.Add(self.labelMergeFile) #row 3, col 1
self.sizerF.Add(self.textMergeFile) #row 3, col 2

self.sizerB = wx.BoxSizer(wx.VERTICAL)
self.sizerB.Add(self.buttonRun, 1, wx.ALIGN_RIGHT|wx.ALL, 5)
self.sizerB.Add(self.buttonExit, 0, wx.ALIGN_RIGHT|wx.ALL, 5)

self.sizer1 = wx.BoxSizer()
self.sizer1.Add(self.sizerF, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 10)
self.sizer1.Add(self.sizerB, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)

self.sizer2 = wx.BoxSizer()
self.sizer2.Add(self.textOutput, 1, wx.EXPAND | wx.ALL, 5)

self.sizerFinal = wx.BoxSizer(wx.VERTICAL)
self.sizerFinal.Add(self.sizer1, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
self.sizerFinal.Add(self.sizer2, 1, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)

self.SetSizerAndFit(self.sizerFinal)


def OnChooseRoot(self, event):
dlg = wx.DirDialog(self, "Choose a directory:", style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
root_path = dlg.GetPath()
self.textChooseRoot.SetValue(root_path)
dlg.Destroy()

def OnRun(self, event):
#Check first if input values are
thread.start_new_thread(self.OnIndex, ())

def OnIndex(self):
#Do something and post to self.textOutput what you do.

def OnExit(self, event):
self.GetParent().Close()


class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="IndexGenerator", size=(430, 330),
style=((wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE |
wx.STAY_ON_TOP) ^ wx.RESIZE_BORDER))
self.CreateStatusBar()

self.fileMenu = wx.Menu()
self.fileMenu.Append(ID_EXIT, "E&xit", "Exit the program")
self.menuBar = wx.MenuBar()
self.menuBar.Append(self.fileMenu, "&File")
self.SetMenuBar(self.menuBar)
wx.EVT_MENU(self, ID_EXIT, self.OnExit)

self.Panel = MainPanel(self)

self.CentreOnScreen()
self.Show()

def OnExit(self, event):
self.Close()

if __name__ == "__main__":
app = wx.App(False)
frame = MainWindow()
app.MainLoop()

[编辑:]这是OnRun和OnIndex方法的摘录。是否有一个()或一个()?
    def OnRun(self, Event=None):
#---Check input values, continue if not wrong
if self.CheckValid() == 0:
#Get root directory
root_path = self.textChooseRoot.GetValue()
#Get scratch workspace
scratch_workspace =self.textScratchWrk.GetValue()
#Get merge file
merge_fil = self.textMergeFile.GetValue()

thread.start_new_thread(self.OnIndex, (root_path,scratch_workspace,merge_fil))

def showmsg(self, msg):
self.textOutput.AppendText(msg + "\n")


def OnIndex(self,root_path,scratch_workspace,merge_fil):
#---PUBSUB - publishes a message to the "show.statusbar"
## msg = "Please wait...Program is running..."
## Publisher().sendMessage(("show.statusbar"), msg)
#---START INDEX GENERATOR CODE
gp.overwriteoutput = 1
gp.OutputMFlag = "DISABLED"
gp.OutputZFlag = "DISABLED"
fc_List = {}


#Get log file. For now a constant. Needs to be changed.
logfil = open("C:\\Python26\\Code\\log.txt", mode = "w")

fold_nr = 0
for root_fold, dirs, files in os.walk(root_path):
root_fold_low = root_fold.lower()
if not root_fold_low.find(".gdb") > -1:
fold_nr += 1
tot_t = time.clock()

wx.CallAfter(self.textOutput.AppendText, ("Mappe : " + str(fold_nr) + " : " + root_fold + "\n"))

最佳答案

与wx对象的所有交互都应在主线程中。

一个简单的解决方法是使用类似wx.CallAfter(self.textOutput.SetValue, "output")而不是self.textOutput.SetValue("output")的方法。

wx.CallAfter一旦到达它,就立即向主偶数循环发送要执行的内容,并且由于主循环位于主线程中,所以一切正常。

更新:工作的合并代码段:

import wx, thread, os, time

ID_EXIT = 110

class Dummy:
pass

gp = Dummy()

class MainPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)

self.buttonRun = wx.Button(self, label="Run")
self.buttonRun.Bind(wx.EVT_BUTTON, self.OnRun )
self.buttonExit = wx.Button(self, label="Exit")
self.buttonExit.Bind(wx.EVT_BUTTON, self.OnExit)

self.labelChooseRoot = wx.StaticText(self, label ="Root catalog: ")
self.labelScratchWrk = wx.StaticText(self, label ="Scratch workspace: ")
self.labelMergeFile = wx.StaticText(self, label ="Merge file: ")

self.textChooseRoot = wx.TextCtrl(self, size=(210, -1))
self.textChooseRoot.Bind(wx.EVT_LEFT_UP, self.OnChooseRoot)
self.textScratchWrk = wx.TextCtrl(self, size=(210, -1))
self.textMergeFile = wx.TextCtrl(self, size=(210, -1))
self.textOutput = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY)

self.sizerF = wx.FlexGridSizer(3, 2, 5, 5)
self.sizerF.Add(self.labelChooseRoot) #row 1, col 1
self.sizerF.Add(self.textChooseRoot) #row 1, col 2
self.sizerF.Add(self.labelScratchWrk) #row 2, col 1
self.sizerF.Add(self.textScratchWrk) #row 2, col 2
self.sizerF.Add(self.labelMergeFile) #row 3, col 1
self.sizerF.Add(self.textMergeFile) #row 3, col 2

self.sizerB = wx.BoxSizer(wx.VERTICAL)
self.sizerB.Add(self.buttonRun, 1, wx.ALIGN_RIGHT|wx.ALL, 5)
self.sizerB.Add(self.buttonExit, 0, wx.ALIGN_RIGHT|wx.ALL, 5)

self.sizer1 = wx.BoxSizer()
self.sizer1.Add(self.sizerF, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 10)
self.sizer1.Add(self.sizerB, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)

self.sizer2 = wx.BoxSizer()
self.sizer2.Add(self.textOutput, 1, wx.EXPAND | wx.ALL, 5)

self.sizerFinal = wx.BoxSizer(wx.VERTICAL)
self.sizerFinal.Add(self.sizer1, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
self.sizerFinal.Add(self.sizer2, 1, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)

self.SetSizerAndFit(self.sizerFinal)


def OnChooseRoot(self, event):
dlg = wx.DirDialog(self, "Choose a directory:", style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
root_path = dlg.GetPath()
self.textChooseRoot.SetValue(root_path)
dlg.Destroy()

def CheckValid(self):
return 0

def OnRun(self, Event=None):
#---Check input values, continue if not wrong
if self.CheckValid() == 0:
#Get root directory
root_path = self.textChooseRoot.GetValue()
#Get scratch workspace
scratch_workspace =self.textScratchWrk.GetValue()
#Get merge file
merge_fil = self.textMergeFile.GetValue()

thread.start_new_thread(self.OnIndex, (root_path,scratch_workspace,merge_fil))

def showmsg(self, msg):
self.textOutput.AppendText(msg + "\n")

def OnIndex(self,root_path,scratch_workspace,merge_fil):
#---PUBSUB - publishes a message to the "show.statusbar"
## msg = "Please wait...Program is running..."
## Publisher().sendMessage(("show.statusbar"), msg)
#---START INDEX GENERATOR CODE
gp.overwriteoutput = 1
gp.OutputMFlag = "DISABLED"
gp.OutputZFlag = "DISABLED"
fc_List = {}


#Get log file. For now a constant. Needs to be changed.
#logfil = open("C:\\Python26\\Code\\log.txt", mode = "w")

fold_nr = 0
for root_fold, dirs, files in os.walk(root_path):
root_fold_low = root_fold.lower()
if not root_fold_low.find(".gdb") > -1:
fold_nr += 1
tot_t = time.clock()

wx.CallAfter(self.textOutput.AppendText, ("Mappe : " + str(fold_nr) + " : " + root_fold + "\n"))

def OnExit(self, event):
self.GetParent().Close()


class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="IndexGenerator", size=(430, 330),
style=((wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE |
wx.STAY_ON_TOP) ^ wx.RESIZE_BORDER))
self.CreateStatusBar()

self.fileMenu = wx.Menu()
self.fileMenu.Append(ID_EXIT, "E&xit", "Exit the program")
self.menuBar = wx.MenuBar()
self.menuBar.Append(self.fileMenu, "&File")
self.SetMenuBar(self.menuBar)
wx.EVT_MENU(self, ID_EXIT, self.OnExit)

self.Panel = MainPanel(self)

self.CentreOnScreen()
self.Show()

def OnExit(self, event):
self.Close()

if __name__ == "__main__":
app = wx.App(False)
frame = MainWindow()
app.MainLoop()

关于multithreading - wxPython:线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6290791/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com