【问题标题】:Tkinter GUI freezing, used Thread then encountered RuntimeError: threads can only be started onceTkinter GUI 死机,使用 Thread 然后遇到 RuntimeError: threads can only be started once
【发布时间】:2023-01-11 00:06:01
【问题描述】:

请帮忙

def change_flag(top_frame, bottom_frame, button1, button2, button3, button4, controller):
    global counter, canvas, my_image, chosen, flag, directory
    canvas.delete('all')
    button5['state'] = DISABLED
    counter += 1

    chosen, options_text = function_options()
    right_answer_flag = get_right_answer_flag(chosen, options_text)
    #pdb.set_trace()

    try:
        location = directory + chosen + format_image
    except:
        controller.show_frame(PlayAgainExit)
        
    my_image = PhotoImage(file=location)
    canvas.create_image(160, 100, anchor=CENTER, image=my_image)

    button1["text"] = options_text[0]
    button2["text"] = options_text[1]
    button3["text"] = options_text[2]
    button4["text"] = options_text[3]

    button1['state'] = NORMAL
    button2['state'] = NORMAL
    button3['state'] = NORMAL
    button4['state'] = NORMAL

##############

        button5 = Button(
            next_frame,
            width=20,
            text="next",
            fg="black",
            #command=lambda: change_flag(top_frame,bottom_frame,button1,button2,button3,button4,controller))
            command=Thread(target=change_flag, args =(top_frame,bottom_frame,button1,button2,button3,button4,controller)).start)
            
        button5.pack(side=RIGHT, padx=5, pady=5)

你好,

我不希望 GUI 冻结,所以我为 button5 使用了线程,但它给了我运行时错误 “你只能启动线程一次”是正确的。但是我应该如何解决这个问题呢?

谢谢你的帮助, 阿拜

【问题讨论】:

  • command 选项上使用 lambda
  • 我看到了您之前的评论并也添加了 lambda,它没有冻结但不会更改下一帧。你想让我发布整个代码吗? button5 = Button( next_frame, width=20, text="next", fg="black", command=lambda: change_flag(top_frame,bottom_frame,button1,button2,button3,button4,controller)) #command=lambda: 线程( target=change_flag, args =(top_frame,bottom_frame,button1,button2,button3,button4,controller)).start)

标签: python-3.x multithreading tkinter


【解决方案1】:
command=Thread(target=change_flag, args=(top_frame,bottom_frame,button1,button2,button3,button4,controller)).start

就是创建线程对象的实例,并将实例的start函数的引用传递给command选项。就像下面这样:

# create an instance of the thread object
t = Thread(target=change_flag, args=(top_frame,bottom_frame,button1,button2,button3,button4,controller))
# pass the start function of the thread object to command option
button5 = Button(..., command=t.start)

因此,当单击按钮时,它会启动线程。再次点击该按钮时,将再次启动同一个线程实例,这是不允许的。

您可以使用lambda,以便在单击按钮时创建并启动线程对象的新实例:

button5 = Button(..., command=lambda: Thread(target=change_flag, args=(top_frame,bottom_frame,button1,button2,button3,button4,controller)).start())

【讨论】:

  • 是的,我明白了,我在之前的评论中也说过同样的话。我确实像这样使用了 lambda,GUI 没有冻结,但 next 现在没有改变框架如果你愿意,我可以粘贴完整的代码。 ############## command=lambda: Thread(target=change_flag, args =(top_frame,bottom_frame,button1,button2,button3,button4,controller)).start)
  • @AbhaySingh 您在使用lambda 时错过了start 之后的()
  • 耶稣,它奏效了,哇,非常感谢。
  • 好家伙,你真是个天才。
猜你喜欢
  • 2015-01-23
  • 2021-01-03
  • 2022-12-01
  • 2018-07-28
  • 2022-12-02
  • 1970-01-01
  • 2022-12-15
  • 2011-09-09
相关资源
最近更新 更多