wxPython:线程问题

发布于 2024-11-14 22:02:12 字数 5545 浏览 1 评论 0原文

我的计划不断扩大。

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

执行此操作时,我在执行 OnRun 时收到错误。它说:

由 <__main__.MainPanel; 的绑定方法 MainPanel.OnIndex 启动的线程中出现未处理的异常<位于 0x526e238 的“wxPanel *”类型的 Swig 对象的代理> >>

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

非常感谢帮助! =)

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"))

My program keeps expanding.

In my MainProgram method in the MainPanel class I'm using some functions from an other program. While using this the GUI hangs until that is finished and I want to solve this by using a new thread for this method.

While doing this I get an error when executing OnRun. It says:

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

It think this has something to do with the OnIndex setting som values to self.textOutput. Now, how can I solve this little problem of mine?

Help is much appreciated! =)

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()

[EDIT:] Here is an extract of the OnRun and OnIndex methods. Is there a () to much or maybe an , ?

    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"))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞别 2024-11-21 22:02:12

所有与 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()

All interaction with wx object should be in the main thread.

An easy fix would be to use something like wx.CallAfter(self.textOutput.SetValue, "output") instead of self.textOutput.SetValue("output").

wx.CallAfter sends to the main even loop what to execute as soon as it gets around to it and since the main loop is in the main thread everything works out fine.

UPDATE: Working merged code snippets:

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()
深巷少女 2024-11-21 22:02:12

您只需使用线程安全的方法将信息发送回主线程即可。正如其他人所说,您不能直接与主线程交互,否则会发生奇怪的事情。这是一篇非常好的文章,介绍了实现这一壮举的各种方法:

http://wiki.wxpython.org/LongRunningTasks< /a>

这是关于该主题的另一篇文章:

http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

You just need to use a threadsafe method to send information back to the main thread. As the others have stated, you cannot interact with the main thread directly or weird things will happen. Here's a really good article on the various ways you can accomplish this feat:

http://wiki.wxpython.org/LongRunningTasks

And here's another article on the subject:

http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/

旧竹 2024-11-21 22:02:12

您无法从另一个线程与 GUI 交互。您的回调应该像这样工作:

def OnRun(self, event):
    <get any data you need from the GUI>
    thread.start_new_thread(self.WorkerThread, (parameter1, parameter2, ...))

def WorkerThread(self, parameter1, parameter2, ...):
    # do time-consuming work here. To send data to
    # the GUI use CallAfter:
    wx.CallAfter(self.textOutput.AppendText, "whatever") 

关键是在生成工作线程之前在主线程中完成所有非耗时的 GUI 交互。一旦工作线程启动,它应该拥有它需要的所有数据。然后它可以继续执行其工作,并使用 CallAfter 与主线程进行通信。

You cannot interact with the GUI from another thread. Your callback should work like this:

def OnRun(self, event):
    <get any data you need from the GUI>
    thread.start_new_thread(self.WorkerThread, (parameter1, parameter2, ...))

def WorkerThread(self, parameter1, parameter2, ...):
    # do time-consuming work here. To send data to
    # the GUI use CallAfter:
    wx.CallAfter(self.textOutput.AppendText, "whatever") 

The key is to do all the non-time-consuming GUI interaction in the main thread before spawning the worker thread. Once the worker thread starts it should have all the data it needs. It can then proceed to do its work, and use CallAfter to communicate back to the main thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文