摆脱线程内的标签?

时间:2011-06-28 05:36:24

标签: python tkinter

所以我有这段代码:

import thread
from Tkinter import *
import random
import time
Admin=Tk()
def moveit(number):
    songas=Label(Admin,text=number,bg='red')
    def ji():
        plad=0.0
        recount=0
        times=0
        while 1:
            plad-=0.1
            recount+=1
            times+=1
            time.sleep(0.5)
            pls=0.0
            pls+=plad


            if recount==4:

                pls=0
                plad=0.0
                recount=0

            songas.place(relx=pls,rely=0.7)


    thread.start_new_thread(ji,())
za=random.random()

button=Button(Admin,text='Press',command=lambda:moveit(str(za)))
button.place(relx=0.2)
Admin.mainloop()

它开始向左移动,但是如果你再次按下“按下”按钮,它会在旧的按钮上面放置更多的数字。 有没有人知道如何删除旧数字,以便只有知道的数字?

2 个答案:

答案 0 :(得分:1)

Tkinter不是线程安全的 - 你不能在除主要线程之外的任何线程中操作小部件,否则你将获得未定义的结果。

你不需要线程。您的代码添加了一个无限循环,但应用程序已经有一个可以利用的无限循环(事件循环)。

如果要移动某个项目,请创建一个执行两项操作的功能。首先,它会执行您想要的任何操作,例如移动项目。其次,它使用标准after方法在短时间内再次调用自身(例如,半秒或500毫秒)。通过这种方式,您可以让事件循环驱动动画,不需要线程,并且您的UI保持响应。

这是一个例子。我怀疑它完全符合你的要求,因为我不确定你想要什么。

import Tkinter as tk
import random

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        self._running = False
        self._relx = None

        tk.Tk.__init__(self, *args, **kwargs)

        self.pack_propagate(False)
        self.configure(width=400, height=400)
        self.label = tk.Label(self, text="hello, world", background="red")
        self.button = tk.Button(self, text="Start", command=self.toggle)
        self.button.pack(side="top")

    def toggle(self):
        '''toggle animation on or off'''
        self._running = not self._running
        if self._running:
            self.button.configure(text="Stop")
            self.moveit()
        else:
            self.button.configure(text="Start")

    def moveit(self):
        '''Animate the label'''
        if not self._running:
            # animation has been stopped
            # hide the label from view.
            self.label.place_forget()

        if self._running:
            if not self.label.winfo_viewable():
                # not visible; establish future locations
                self._relx = [.5, .4, .3, .2, .1, 0]
            relx = self._relx.pop(0)
            self._relx.append(relx)
            self.label.place(relx=relx, rely=0.7)
            self.after(1000, self.moveit)

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

答案 1 :(得分:0)

你必须用信号通知旧线程以某种方式退出。使用锁执行可能最简单 - 在创建新线程并获取锁时创建锁。并且在不再需要线程时释放它。然后线程只需要在主循环中检查它的锁是否仍然被锁定 - 如果不是,它将删除标签并退出。这里是代码的修改版本(用适当的代码替换“在这里删除标签”注释):

import thread
from Tkinter import *
import random
import time
Admin=Tk()
lock = None
def moveit(number):
    global lock
    songas=Label(Admin,text=number,bg='red')
    def ji(lock):
        plad=0.0
        recount=0
        times=0
        while 1:
            plad-=0.1
            recount+=1
            times+=1
            time.sleep(0.5)
            pls=0.0
            pls+=plad


            if recount==4:

                pls=0
                plad=0.0
                recount=0

            songas.place(relx=pls,rely=0.7)

            if not lock.locked():
                # Remove label here
                break

    if lock:
        # Signal old thread to exit
        lock.release()
    lock = thread.allocate_lock()
    lock.acquire()
    thread.start_new_thread(ji,(lock,))

za=random.random()

button=Button(Admin,text='Press',command=lambda:moveit(str(za)))
button.place(relx=0.2)
Admin.mainloop()