【问题标题】:tkinkter thread not terminating (gif runs in endless loop)tkinter 线程未终止(gif 在无限循环中运行)
【发布时间】:2017-05-23 00:25:35
【问题描述】:

我正在尝试通过按下按钮来链接 2 个操作。我正在使用线程 一个函数“回调”打印一条消息,另一个函数创建一个标签 显示 gif 动画。当我尝试穿线并按下按钮运行时 他们,gif无限(连续)显示,但我想拥有它 一旦“回调”完成运行,就从 GUI 中删除(删除)。任何帮助表示赞赏。

from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import threading
import time

root = Tk()
root.title('Title')

def callback():
     print('this message')
     time.sleep(0.5)

def animate():

    while True:

        try:

            time.sleep(0.04)
            img = PhotoImage(file='path',format="gif - {}".format(num))
            label1 = ttk.Label(root, image=img)
            label1.grid(row=0, column=1)
            num+=1

        except:

            num=0
def thr():

    t1= threading.Thread(target=callback)
    t2= threading.Thread(target=animate)
    t1.start()
    t2.start()

button = ttk.Button(root, text='click', command=thr).grid(row=0, column=1, sticky=N)
entry = scrolledtext.ScrolledText(root, width=30, heigh=10, wrap=WORD)
entry.grid(row=0, column=0)

entry.focus()
root.mainloop()

【问题讨论】:

  • 您可以替换现有标签中的图像,而不是一次又一次地创建新标签。现在您在同一个单元格中有数千个标签 - 一个在另一个之上。顺便说一句:tkinter 具有函数 root.after(milliseconds, function_name),您可以使用它来代替 thread
  • 为了使代码更具可读性,您可以将所有函数放在root = Tk()之前
  • if num > 10: break 在 10 张图片后离开 while True 并结束线程怎么样。
  • 将图像设置为None - label1['image'] = None 或销毁标签 - label1.destroy()

标签: python multithreading tkinter gif


【解决方案1】:

您可以使用变量通知第二个线程第一个线程结束。

running = False

但这可能不是最好的方法——也许您应该使用模块queue 将信息从一个线程发送到另一个线程。

您可以使用label1.destroy() 删除标签和图像,但您只需创建一次标签,以后只需更改此标签中的图像。

label1['image'] = img

代码:

from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import threading
import time
#from PIL import Image, ImageTk # for `png`

# --- functions ----

def callback():
    # inform function to use external/global variable because you use `=`
    global running

    print('callback: start')
    time.sleep(2)
    print('callback: end')

    # inform other thread to end running
    running = False

def animate():
    print('animate: start')

    while running:
        try:
            time.sleep(0.04)
            img = PhotoImage(file='path', format="gif - {}".format(num))
            #img = Image.open('test/image-{}.png'.format(num)) # for `png`
            #img = ImageTk.PhotoImage(img) # for `png`
            #label1.img = img # solution for garbage collector problem # for `png`
            label1['image'] = img
            num += 1
        except:
            num = 0

    #label1.img = None # doesn't work
    #label1['image'] = None # doesn't work

    # destroy label 
    label1.destroy()

    print('animate: end')

def thr():
    # inform function to use external/global variable because you use `=`
    global running
    global label1

    # create new label
    label1 = ttk.Label(root)
    label1.grid(row=0, column=1)

    running = True

    t1 = threading.Thread(target=callback)
    t2 = threading.Thread(target=animate)
    t1.start()
    t2.start()

# --- main ---

# create global variables
running = False
label1 = None

# - GUI -

root = Tk()
root.title('Title')

button = ttk.Button(root, text='click', command=thr)
button.grid(row=0, column=1, sticky=N)

entry = scrolledtext.ScrolledText(root, width=30, heigh=10, wrap=WORD)
entry.grid(row=0, column=0)

entry.focus()
root.mainloop()

编辑:你也可以使用

while t1.is_alive():

而不是while running:


编辑:您也可以使用root.after 而不是第二个线程。

from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import threading
import time
#from PIL import Image, ImageTk # for `png`

# --- functions ----

def callback():
    # inform function to use external/global variable because you use `=`
    global running

    print('callback: start')
    time.sleep(2)
    print('callback: end')

def animate(num=0):
    try:
        img = PhotoImage(file='path', format="gif - {}".format(num))
        #img = Image.open('test/ball-{}.png'.format(num)) # for `png`
        #img = ImageTk.PhotoImage(img) # for `png`
        #label1.img = img # solution for garbage collector problem # for `png`
        label1['image'] = img
        num += 1
    except:
        num = 0

    if t1.is_alive():
        # execute again after 4ms
        root.after(4, animate, num) # 4ms = 0.04s
    else:
        # destroy label 
        label1.destroy()
        print("animate: end")


def thr():
    # inform function to use external/global variable because you use `=`
    global label1
    global t1

    # create new label
    label1 = ttk.Label(root)
    label1.grid(row=0, column=1)

    t1 = threading.Thread(target=callback)
    t1.start()

    print("animate: start")
    animate(0)

# --- main ---

# create global variables
label1 = None
t1 = None

# - GUI -

root = Tk()
root.title('Title')

button = ttk.Button(root, text='click', command=thr)
button.grid(row=0, column=1, sticky=N)

entry = scrolledtext.ScrolledText(root, width=30, heigh=10, wrap=WORD)
entry.grid(row=0, column=0)

entry.focus()
root.mainloop()

【讨论】:

  • 嘿,谢谢!让我早上第一件事试试,我会告诉你的!
  • 我怀疑这可能有效。会让你知道!谢谢你,真的!
  • 第一个代码没有解决问题,我不断得到 gif 无限循环,它不会破坏自己。第二个代码甚至不显示 gif。回调函数完成
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
  • 2015-07-31
  • 2021-06-30
  • 1970-01-01
  • 2012-04-30
相关资源
最近更新 更多