如何使用wxPython将值正确地继承到线程类中

时间:2015-08-17 09:27:43

标签: python python-2.7 wxpython wxwidgets

我有一个控制某些硬件的wxPython gui。 我需要一个按钮来在功能运行时禁用。该函数还接收参数值

让我说我有这个按下按钮的功能:

    def button_press(self, event):

       in_val = self.num_in.GetValue() #grabs a value from a NumCtrl
       TheThread(in_val) #initiates the thread with argument
       btn = event.GetEventObject() 
       btn.Disable() #disables button

此函数转到以下线程类:

    class TheThread(Thread):
def __init__(self, in_val):

    """Init Worker Thread Class."""
    Thread.__init__(self)

    self.run(in_val)

def run(self, in_val):
    print val
    time.sleep(5)

    wx.CallAfter(Publisher.sendMessage, "ctrl")
    """
    threadsafe method to call a pub.subscribe that runs a 
    function to re-enable button
    """

这种方式不正常,因为gui在功能运行期间冻结,并且按钮没有正确禁用。

如何正确继承此参数以使其正常运行? 也许是涉及self.start()方法的东西?

2 个答案:

答案 0 :(得分:2)

您对start方法的猜测是正确的。

run是在新线程上调用的方法,而start是您要调用的方法,以告诉Thread对象执行此操作。

在您的示例中,通过自己调用run,您在主线程上调用run并且根本没有进行任何线程。 (线程永远不会启动)

class TheThread(Thread):
    def __init__(self, in_val):

        """Init Worker Thread Class."""
        Thread.__init__(self)

        self.in_val = in_val
        self.start()

    def run(self):
        print self.in_val
        time.sleep(5)

        wx.CallAfter(Publisher.sendMessage, "ctrl")
        """
        threadsafe method to call a pub.subscribe that runs a 
        function to re-enable button
        """

答案 1 :(得分:0)

请勿从run()致电__init__()run()睡5秒然后返回。但是__init__()需要在对象完全实例化之前返回,并且调用代码会阻塞,直到__init__()返回。大多数函数调用都是相同的情况,即调用代码在继续执行之前等待函数返回(或在生成器的情况下产生)。

要解决此问题,请从__init__()移除对run()的调用,并调用start()实例上的TheThread()方法:

def button_press(self, event):
    in_val = self.num_in.GetValue()
    TheThread(in_val).start()
    btn = event.GetEventObject() 
    btn.Disable() #disables button

class TheThread(Thread):
    def __init__(self, in_val):
        """Init Worker Thread Class."""
        super(TheThread, self).__init__()
        self.in_val = in_val

    def run(self):
        print self.in_val
        time.sleep(5)
        wx.CallAfter(Publisher.sendMessage, "ctrl")

您也可以在start()内调用线程的__init__()方法,但更常见的方法是在线程实例本身上调用start。这是一种更灵活的解决方案,因为可以先创建线程然后再创建线程,例如如果你有一个线程池,其中首先创建所有线程然后一起启动。