TkInter 在线程运行时禁用按钮

2024-04-10

我有一个应用程序,当按下按钮时尝试生成文本。大多数情况下,文本生成速度很快,但有一个函数需要大约 20 秒才能执行(取决于文本量)。在此过程中,GUI 经常冻结,因此我将该函数转移到一个单独的线程上,并且该字段上的一切都很好。

现在我遇到了按钮问题。当需要一些时间执行的函数正在运行时,用户仍然可以单击该按钮,并且该函数将在第一次调用仍在处理时执行多次。 我想通过在该函数运行时禁用所有按钮来防止这种情况,但我无法让线程正常工作。

这是我的代码:

def generate_text():
    choice = dropdown_choice.get()
    if context_obj.context_text.get() == '':
        if choice == 'OpenAI':
            context = 'Some random context text'

        else:
            context = ' '
    else:
        context = context_obj.context_text.get()

    if choice == 'OpenAI':
        progress.start(50)
        progress_bar_text = Label(text='Please wait while the text is being generated',
                            background='#E5F2FF',
                            font=("Helvetica", 12))

        progress_bar_text.place(relx=.2, 
                            rely=.66, 
                            anchor="c")

         # multithreading for the OpenAI text generation
        q = queue.Queue()
        thread1 = Thread(target=openAI_generator.sample, args=[text_amount.get(), temperature.get(), context, q])
        thread1.start()

        def display_AI_text(q):
            openAI_text = q.get()
            generated_text.configure(state='normal')
            generated_text.delete(1.0,END)
            generated_text.insert(tk.END, openAI_text)
            generated_text.configure(state='disabled')

            progress.stop()
            progress_bar_text.place_forget()

        thread2 = Thread(target=display_AI_text, args=[q])
        thread2.start()

在这段代码中,thread1正在执行该函数并且thread2正在从该函数获取输入并显示它。

我想做的是,同时thread2正在执行时,所有按钮都将被禁用,当线程完成时,按钮将再次启用。

我尝试添加:

thread2 = Thread(target=display_AI_text, args=[q])
generate_button.config(state="disabled")
thread2.start()

进而:

thread2.join()
generate_button.config(state="normal")

但这段代码会冻结应用程序。我假设主线程正在等待thread2完成,这就是它没有响应的原因。

有谁知道解决这个问题的方法?


在许多 GUI 中,您无法在线程中更改 GUI - 您必须在主进程中执行此操作。

您可以使用队列将信息发送到将更新 GUI 的主进程。

在 Tkinter 中你可以使用

root.after(time_in_milliseconds, function_name) 

定期运行可以检查此队列中的消息的函数。

或者可以定期检查

thread2.is_alive()

而不是使用thread2.join()因为is_alive()不阻止代码。

import tkinter as tk
from threading import Thread
import time

def long_running_function():
    print('start sleep')
    time.sleep(3)
    print('end sleep')

def start_thread():
    global t
    global counter

    b['state'] = 'disable'
    counter = 0

    t = Thread(target=long_running_function)
    t.start()

    check_thread()
    # or check after 100ms
    # root.after(100, check_thread) 

def check_thread():
    global counter

    if not t.is_alive():
        b['state'] = 'normal'
        l['text'] = ''
    else:
        l['text'] = str(counter)
        counter += 0.1

        # check again after 100ms
        root.after(100, check_thread) 

#-----------------------------------------------------

# counter displayed when thread is running        
counter = 0

root = tk.Tk()

l = tk.Label(root)
l.pack()

b = tk.Button(root, text="Start", command=start_thread)
b.pack()

root.mainloop()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TkInter 在线程运行时禁用按钮 的相关文章

  • 如何在flask中使用g.user全局

    据我了解 Flask 中的 g 变量 它应该为我提供一个全局位置来存储数据 例如登录后保存当前用户 它是否正确 我希望我的导航在登录后在整个网站上显示我的用户名 我的观点包含 from Flask import g among other
  • 使用带有关键字参数的 map() 函数

    这是我尝试使用的循环map功能于 volume ids 1 2 3 4 5 ip 172 12 13 122 for volume id in volume ids my function volume id ip ip 我有办法做到这一点
  • 使用 matplotlib 绘制时间序列数据并仅在年初显示年份

    rcParams date autoformatter month b n Y 我正在使用 matpltolib 来绘制时间序列 如果我按上述方式设置 rcParams 则生成的图会在每个刻度处标记月份名称和年份 我怎样才能将其设置为仅在每
  • Python - StatsModels、OLS 置信区间

    在 Statsmodels 中 我可以使用以下方法拟合我的模型 import statsmodels api as sm X np array 22000 13400 47600 7400 12000 32000 28000 31000 6
  • 如何使用Conda下载python包并随后离线安装?

    我知道通过 pip 我可以使用以下命令下载 Python 包 但 pip install 破坏了我的内部包依赖关系 当我做 pip download
  • 从字符串中删除识别的日期

    作为输入 我有几个包含不同格式日期的字符串 例如 彼得在16 45 我的生日是1990年7月8日 On 7 月 11 日星期六我会回家 I use dateutil parser parse识别字符串中的日期 在下一步中 我想从字符串中删除
  • 使用 on_bad_lines 将 pandas.read_csv 中的无效行写入文件

    我有一个 CSV 文件 我正在使用 Python 来解析该文件 我发现文件中的某些行具有不同的列数 001 Snow Jon 19801201 002 Crom Jake 19920103 003 Wise Frank 19880303 l
  • 如何从网页中嵌入的 Tableau 图表中抓取工具提示值

    我试图弄清楚是否有一种方法以及如何使用 python 从网页中的 Tableau 嵌入图形中抓取工具提示值 以下是当用户将鼠标悬停在条形上时带有工具提示的图表示例 我从要从中抓取的原始网页中获取了此网址 https covid19 colo
  • 测试 python Counter 是否包含在另一个 Counter 中

    如何测试是否是pythonCounter https docs python org 2 library collections html collections Counter is 包含在另一个中使用以下定义 柜台a包含在计数器中b当且
  • 基于代理的模拟:性能问题:Python vs NetLogo & Repast

    我正在 Python 3 中复制一小段 Sugarscape 代理模拟模型 我发现我的代码的性能比 NetLogo 慢约 3 倍 这可能是我的代码的问题 还是Python的固有限制 显然 这只是代码的一个片段 但 Python 却花费了三分
  • 绘制方程

    我正在尝试创建一个函数 它将绘制我告诉它的任何公式 import numpy as np import matplotlib pyplot as plt def graph formula x range x np array x rang
  • 如何在Python中获取葡萄牙语字符?

    我正在研究葡萄牙语 角色看起来很奇怪 我怎样才能解决这个问题 代码 import feedparser import random Vou definir os feeds feeds conf feedurl http pplware s
  • 使用 \r 并打印一些文本后如何清除控制台中的一行?

    对于我当前的项目 有一些代码很慢并且我无法使其更快 为了获得一些关于已完成 必须完成多少的反馈 我创建了一个进度片段 您可以在下面看到 当你看到最后一行时 sys stdout write r100 80 n I use 80覆盖最终剩余的
  • 向 Altair 图表添加背景实心填充

    I like Altair a lot for making graphs in Python As a tribute I wanted to regenerate the Economist graph s in Mistakes we
  • 对年龄列进行分组/分类

    我有一个数据框说df有一个柱子 Ages gt gt gt df Age 0 22 1 38 2 26 3 35 4 35 5 1 6 54 我想对这个年龄段进行分组并创建一个像这样的新专栏 If age gt 0 age lt 2 the
  • 有没有办法检测正在运行的代码是否正在上下文管理器内执行?

    正如标题所述 有没有办法做到这样的事情 def call back if called inside context print running in context else print called outside context 这将
  • Python:如何将列表列表的元素转换为无向图?

    我有一个程序 可以检索 PubMed 出版物列表 并希望构建一个共同作者图 这意味着对于每篇文章 我想将每个作者 如果尚未存在 添加为顶点 并添加无向边 或增加每个合著者之间的权重 我设法编写了第一个程序 该程序检索每个出版物的作者列表 并
  • 如何计算 pandas 数据帧上的连续有序值

    我试图从给定的数据帧中获取连续 0 值的最大计数 其中包含来自 pandas 数据帧的 id date value 列 如下所示 id date value 354 2019 03 01 0 354 2019 03 02 0 354 201
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何将输入读取为数字?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 Why are x and y下面的代码中使用字符串而不是整数 注意 在Python 2

随机推荐