需要Python TKinter线程帮助

需要Python TKinter线程帮助,python,multithreading,user-interface,tkinter,Python,Multithreading,User Interface,Tkinter,我正在尝试创建一个与RS232串行对象通信的GUI。我将为我所面临的问题提供一个类似的场景。我想创建一个有两个按钮的框架,开始和停止。“开始”按钮调用“foo”函数: status = True def foo(): n = 0 while(getStatus()): print n n += 1 sleep(0) 这个foo函数一直运行,直到我按下stop def getStatus(): return status def s

我正在尝试创建一个与RS232串行对象通信的GUI。我将为我所面临的问题提供一个类似的场景。我想创建一个有两个按钮的框架,开始和停止。“开始”按钮调用“foo”函数:

status = True

def foo():
   n = 0
   while(getStatus()):
       print n
       n += 1
       sleep(0)
这个foo函数一直运行,直到我按下stop

def getStatus():
   return status

def stop():
   status = False
我知道Tkinter是单线程的,一旦我按下“开始”,GUI就会冻结。我知道这可以通过
after
函数实现,但我严格希望使用线程化。穿线是否可能?如果有,请提供一个示例代码?多谢各位

以下是一些(尚未完善的)代码:

丢失/损坏的内容,但您没有要求,我添加了链接:

  • 它不使用locks=>set调用可能会停止,因为它们可以同时发生。(这很容易)
  • 它从另一个线程更新gui。看
  • 可能更多(不是线程大师)
也用于停止线程查看

以下是一些(尚未完善的)代码:

丢失/损坏的内容,但您没有要求,我添加了链接:

  • 它不使用locks=>set调用可能会停止,因为它们可以同时发生。(这很容易)
  • 它从另一个线程更新gui。看
  • 可能更多(不是线程大师)
也用于停止线程查看


我不太明白您的问题,只需启动一个线程(thread.threading)并让它检查状态。用锁/信号灯保护状态,你会没事的。我不知道python中的原子集在您的情况下会起作用。因为您不想更新gui,所以从控制台启动线程没有什么区别。@ted:我不知道这意味着什么。我对GUI编码非常陌生。如果不是示例代码,你能给我指一些有用的链接/文档吗?如果我有时间,我会尝试今晚把一些东西放在一起,如果到那时还没有人。很抱歉,我不能早点做,不过我必须看一下,因为我没有用python做太多的线程处理。谢谢。我真的很感激。我不太明白你的问题,只需启动一个线程(thread.threading)并让它检查状态。用锁/信号灯保护状态,你会没事的。我不知道python中的原子集在您的情况下会起作用。因为您不想更新gui,所以从控制台启动线程没有什么区别。@ted:我不知道这意味着什么。我对GUI编码非常陌生。如果不是示例代码,你能给我指一些有用的链接/文档吗?如果我有时间,我会尝试今晚把一些东西放在一起,如果到那时还没有人。很抱歉,我不能早点做,不过我必须看一下,因为我没有用python做太多的线程处理。谢谢。我非常感谢,谢谢。我可以在一些版本之后运行你的代码。但是,当我点击开始按钮时,它会打印一条消息,说明super()方法需要一个参数,但没有给出任何参数。在timer类中super应该有什么参数?您正在运行Python2.x吗?这是为Python3编写的。例如,
tkinter
模块过去在2.x中有一个大写的
T
,我相信。如果是这种情况,那么实际上有两个参数将以这里使用的方式使用,我们希望super的类名和绑定super对象的实例。所以这行应该是:
super(timer,self)。\uuu init\uuuu()
。这样一来,super的优势就消失了,你也可以编写
threading.Thread.\uuu init\uuuuuuuuuuuuuuuuuuself)
,不过我喜欢super(熟悉py3的super)。是的,我正在运行2.x,所以不得不更改一些语法。再次感谢,谢谢。我可以在一些版本之后运行你的代码。但是,当我点击开始按钮时,它会打印一条消息,说明super()方法需要一个参数,但没有给出任何参数。在timer类中super应该有什么参数?您正在运行Python2.x吗?这是为Python3编写的。例如,
tkinter
模块过去在2.x中有一个大写的
T
,我相信。如果是这种情况,那么实际上有两个参数将以这里使用的方式使用,我们希望super的类名和绑定super对象的实例。所以这行应该是:
super(timer,self)。\uuu init\uuuu()
。这样一来,super的优势就消失了,你也可以编写
threading.Thread.\uuu init\uuuuuuuuuuuuuuuuuuself)
,不过我喜欢super(熟悉py3的super)。是的,我正在运行2.x,所以不得不更改一些语法。再次感谢
import time
import tkinter
from tkinter import ttk
import threading  

#gui
root = tkinter.Tk()
root.title("Threading demo")

status = tkinter.StringVar()
elapsed = tkinter.StringVar()
error = tkinter.StringVar()

#thread
class timer(threading.Thread):
    def __init__(self):
        super().__init__()
        self.stopped = False
        #your code here, don't need init if you have no code



    def run(self):
        status.set('running')

        while not self.isStopped():
            time.sleep(1)

            try:
                oldtime = int(elapsed.get())
            except ValueError:
                oldtime = 0

            elapsed.set(oldtime+1)

        status.set('stopped')
        time.sleep(2)

    def isStopped(self):
        return self.stopped



    def stop(self):
        self.stopped = True



#starts/stops thread (manages it)
class threadedOp(object):
    def __init__(self):
        self.thread = None


    def run(self):
        if self.thread == None:
            self.thread = timer()
            status.set('starting')
            self.thread.start()
        else:
            error.set('Thread already running')


    def stop(self):
        if self.thread != None:
            status.set('stopping')
            self.thread.stop()
            self.thread.join()
            error.set('Join complete')
            self.thread = None
        else:
            error.set('No thread to stop')

op = threadedOp()

#remaining gui
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(tkinter.N, tkinter.W, tkinter.E, tkinter.S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)

ttk.Label(mainframe, textvariable=elapsed).grid(column=1, row=1, sticky=(tkinter.W, tkinter.E))
ttk.Label(mainframe, textvariable=status).grid(column=2, row=1, sticky=(tkinter.W, tkinter.E))
ttk.Label(mainframe, textvariable=error).grid(column=1, row=3, sticky=(tkinter.W, tkinter.E))
ttk.Button(mainframe, text="Start", command=op.run).grid(column=1, row=2, sticky=tkinter.W)
ttk.Button(mainframe, text="Stop", command=op.stop).grid(column=2, row=2, sticky=tkinter.W)

root.mainloop()