尝试修复 tkinter GUI 冻结问题(使用线程)

2024-03-18

我有一个 Python 3.x 报告创建器,它的 I/O 限制非常大(由于 SQL,而不是 Python),以至于主窗口将“锁定”minutes在创建报告时。

所需要的只是能够在 GUI 锁定时使用标准窗口操作(移动、调整大小/最小化、关闭等)(GUI 上的其他所有内容都可以保持“冻结”状态,直到所有报告完成)。

添加了 20181129 :换句话说,tkinter 必须仅控制应用程序窗口的内容,并将所有标准(外部)窗口控件的处理留给操作系统。如果我能做到这一点,我的问题就会消失,并且我不需要全部使用线程/子进程(冻结成为可接受的行为,类似于禁用“执行报告”按钮)。

什么是最简单/最简单的方法(=minimum对现有代码的干扰)这样做 - 理想情况下以与 Python >= 3.2.2 一起工作的方式并且以跨平台的方式(即至少在 Windows 和 Linux 上工作)。


下面的所有内容都是支持信息,更详细地解释了该问题、尝试的方法以及遇到的一些微妙问题。

需要考虑的事项:

  • 用户选择他们的报告,然后按主窗口上的“创建报告”按钮(当实际工作开始并发生冻结时)。所有报告完成后,报告创建代码将显示(顶级)“完成”窗口。关闭此窗口将启用主窗口中的所有内容,允许用户退出程序或创建更多报告。

  • 添加了 20181129:以明显随机的间隔(相隔几秒)我可以移动窗口。

  • 除了显示“完成”窗口之外,报告创建代码不以任何方式涉及 GUI 或 tkinter。

  • 报告创建代码生成的一些数据必须出现在“完成”窗口中。

  • 没有理由“并行化”报告创建,特别是因为使用相同的 SQL 服务器和数据库来创建所有报告。

  • 如果它影响解决方案:我最终需要在创建每个报告时在 GUI 上显示报告名称(现在显示在控制台上)。

  • 第一次使用 python 进行线程/子处理,但熟悉其他语言。

  • 添加了 20181129 :开发环境是使用 Eclipse Oxygen(pydev 插件)的 Win 10 上的 64 位 Python 3.6.4。应用程序必须至少可移植到 Linux。


最简单的答案似乎是使用线程。只需要一个额外的线程(创建报告的线程)。受影响的线路:

DoChosenReports()  # creates all reports (and the "Done" window)

当更改为:

from threading import Thread

CreateReportsThread = Thread( target = DoChosenReports )
CreateReportsThread.start()
CreateReportsThread.join()  # 20181130: line omitted in original post, comment out to unfreeze GUI 

成功生成报告,其名称在创建时显示在控制台上。
但是,GUI 保持冻结状态,并且“完成”窗口(现在由新线程调用)永远不会出现。这让用户陷入困境,无能为力和 想知道发生了什么(如果有的话)(这就是为什么我想在创建文件名时在 GUI 上显示文件名)。

顺便说一句,报告完成后,报告创建线程必须在显示“完成”窗口之前(或之后)悄悄自杀。

我也尝试过使用

from multiprocessing import Process
    
ReportCreationProcess = Process( target = DoChosenReports )
ReportCreationProcess.start()

但这与主要程序“如果(_name_ == '_main_) :' “ 测试。


Added 20181129 : Just discovered the wait_variable() universal widget method https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/universal.html). Basic idea is to launch the create report code as an do-forever thread (daemon?) controlled by this method (with execution controlled by the Do reports button in the GUI).


从网络研究中我知道所有 tkinter 操作都应该在主(父)线程内进行, 这意味着我必须将“完成”窗口移至该线程。
我还需要该窗口来显示它从“子”线程接收的一些数据(三个字符串)。我正在考虑使用应用程序级全局变量作为信号量(仅由创建报告线程写入并且仅由主程序读取)来传递数据。我知道对于两个以上的线程来说这可能会有风险,但对于我的简单情况来说,做更多的事情(例如使用队列?)似乎有点矫枉过正。


总结一下:当窗口因任何原因冻结时,允许用户操作(移动、调整大小、最小化等)应用程序主窗口的最简单方法是什么。换句话说,操作系统(而不是 tkinter)必须控制主窗口的框架(外部)。
答案需要以跨平台的方式在 python 3.2.2+ 上工作(至少在 Windows 和 Linux 上)


您将需要两个函数:第一个函数封装了程序的长时间运行工作,第二个函数创建一个处理第一个函数的线程。如果您需要在线程仍在运行时用户关闭程序时立即停止线程(不推荐),请使用daemon标记或调查Event https://docs.python.org/3/library/threading.html#threading.Event对象。如果您不希望用户在完成之前再次调用该函数,请在该按钮启动时禁用该按钮,然后在结束时将该按钮设置回正常状态。

import threading
import tkinter as tk
import time

class App:
    def __init__(self, parent):
        self.button = tk.Button(parent, text='init', command=self.begin)
        self.button.pack()
    def func(self):
        '''long-running work'''
        self.button.config(text='func')
        time.sleep(1)
        self.button.config(text='continue')
        time.sleep(1)
        self.button.config(text='done')
        self.button.config(state=tk.NORMAL)
    def begin(self):
        '''start a thread and connect it to func'''
        self.button.config(state=tk.DISABLED)
        threading.Thread(target=self.func, daemon=True).start()

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

尝试修复 tkinter GUI 冻结问题(使用线程) 的相关文章

  • 如何在python中确定过去的时区特定日期是否是夏令时?

    有没有办法检查特定时区在我指定的日期是否处于夏令时 test dt datetime year 2015 month 2 day 1 pst pytz timezone America Los Angeles test dt pst loc
  • 从 Python 将分层 JSON 数据写入 Excel xls?

    我想将一些数据从 python 写入 xlsx 我目前将其存储为 JSON 但它从 Python 中输出什么并不重要 单个文章的 JSON 如下所示 Word Count 50 Key Words Blah blah blah Foo Fr
  • 将相同的 Patch 实例添加到 matplotlib 中的多个子图中

    我正在尝试将补丁的相同实例添加到 matplotlib 中的多个轴 这是最小的例子 import matplotlib pyplot as mpl plt import matplotlib patches as mpl patches f
  • 监控培训课程如何运作?

    我试图理解使用之间的区别tf Session and tf train MonitoredTrainingSession 以及我可能更喜欢其中之一 似乎当我使用后者时 我可以避免许多 杂务 例如初始化变量 启动队列运行程序或设置文件编写器以
  • 多个列表和大小的所有可能排列

    在 python 中使用以下命令很容易计算简单的排列itertools permutations https docs python org 3 library itertools html itertools permutations 你
  • Python:绘制甘特图的模块

    有没有一个好的Python绘图模块甘特图 http en wikipedia org wiki Gantt chart 我试过了开罗情节 http linil wordpress com 2008 09 16 cairoplot 11 但它
  • Python 中使用 globals() 的原因?

    Python 中有 globals 函数的原因是什么 它只返回全局变量的字典 这些变量已经是全局的 所以它们可以在任何地方使用 我只是出于好奇而问 试图学习Python def F global x x 1 def G print glob
  • Python pip install 未找到所需版本

    我使用的是Python 3 7 pip版本 10 0 1 操作系统 Windows 10 在 CMD 中 我使用以下命令安装依赖项 Python m pip install requirements txt 但它显示此消息 找不到满足要求的
  • Erlang 进程如何(如果有的话)映射到内核线程?

    Erlang 因能够支持许多轻量级进程而闻名 它之所以能做到这一点 是因为它们不是传统意义上的进程 甚至不是 P 线程中的线程 而是完全在用户空间中的线程 这很好 实际上很棒 那么 Erlang 线程如何在多核 多处理器环境中并行执行呢 当
  • Django - 使 ModelForm(ImageField 的)仅接受某些类型的图像

    我将 Pillow 2 3 0 与 Django 一起使用 并且在 models py 中有一个 ImageField 如下所示 class UserImages models Model user models ForeignKey Us
  • 在 Python 中将嵌套字典位置作为参数传递

    如果我有一个嵌套字典 我可以通过索引来获取键 如下所示 gt gt gt d a b c gt gt gt d a b c 我可以将该索引作为函数参数传递吗 def get nested value d path a b return d
  • 如何删除 pip 安装的所有软件包?

    如何从当前激活的虚拟环境中卸载 pip 安装的所有软件包 我发现这个片段作为替代解决方案 与重新创建 virtualenv 相比 删除库更加优雅 pip freeze xargs pip uninstall y 如果您通过 VCS 安装了软
  • 如何使用 Python 实现并行 gzip 压缩?

    使用python压缩大文件 https stackoverflow com questions 9518705 big file compression with python给出了一个很好的例子来说明如何使用例如bz2 纯粹用 Pytho
  • 从 python 文件调用 Julia 函数

    我能够创建一个 docker 环境 然后按照这个线程我有一个用 Julia 编写的高性能函数 如何从 Python 中使用它 https stackoverflow com questions 64241264 i have a high
  • Matplotlib:检查空图

    我有一个循环加载并绘制一些数据 如下所示 import os import numpy as np import matplotlib pyplot as plt for filename in filenames plt figure i
  • 访问影子 DOM 中的元素

    是否有可能查找 Shadow DOM 中的元素与蟒蛇硒 示例用例 我有这个input with type date
  • 在多线程环境中捕获信号

    我有一个大型程序 需要尽可能具有弹性 并且有大量线程 我需要捕获所有信号SIGBUS SIGSEGV 并在必要时重新初始化有问题的线程 或者禁用该线程以继续减少功能 我的第一个想法是做一个setjump 然后设置信号处理程序 可以记录问题
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • 如何通过 Selenium 内部的文本查找按钮(Python)?

    我有以下三个按钮 我不知道如何获取其中的文本 例如异常值 我试过browser find element by link text Outliers click 但出现 无法找到元素 错误 我该怎么做 See find element by
  • 如何从 python 中的字符串中删除 ANSI 转义序列

    这是包含我的字符串的片段 ls r n x1b 00m x1b 01 31mexamplefile zip x1b 00m r n x1b 01 31m 该字符串是从我执行的 SSH 命令返回的 我无法使用当前状态下的字符串 因为它包含 A

随机推荐

  • 为什么默认情况下允许进程外服务器“本地启动”,但不允许“本地激活”?

    我当前需要创建一个 COM 对象 该对象由 ASP NET 处理程序内部的进程外 COM 服务器提供服务 因此 每次部署 COM 服务器时 我都必须启动 DCOM Config 并更改安全设置 具体来说 我需要确保本地用户 ASPNET 允
  • Python:无法将浮点 NaN 转换为整数

    我应用返回浮动的移动平均逻辑 我先将该 float 转换为 int 然后再使用它在 OpenCV 中绘制线条 但出现以下错误 ValueError cannot convert float NaN to integer 示例代码 def m
  • API 设计:公开 XML 或对象 #2

    我最近问了这个问题 公开 XML 或对象 https stackoverflow com questions 368521 api design expose xml or objects 感谢大家的回复 有一点需要澄清 API 始终可以远
  • 如何在 PostgreSQL 中以事务方式插入 max(order_field) + 1 行

    我需要在 PostgreSQL 表中插入一行 其中有一列包含表行子集上同一列的最大值 1 该列用于对该子集中的行进行排序 我正在尝试更新插入后触发器中的列值 但我在不同行中获取该列的重复值 在短时间内进行大量插入的并发环境中 避免子集中排序
  • 如何从 SSL 证书中提取密钥?

    我有一个在以下网站购买的 SSL 证书 pem crt der格式 我想知道如何从证书中获取密钥文件 有什么办法可以做到这一点吗 您可以提取公钥 这的用处有限 也许您将在其他不使用证书的工具 例如 SSH 或 PGP 中使用相同的密钥 使用
  • JTable 的 ScrollPane 行为异常

    我有一个JPanel组件与JTable在它里面 当我运行下面编写的代码时 表格会正确呈现和更新 一旦我尝试使用scrollPane方法 该表根本不呈现 谁能向我解释这是为什么 private static class GameHistory
  • Java中有没有内置的方法来增加字体大小?

    Java中有没有内置的方法来增加字体大小 The Font http java sun com javase 6 docs api java awt Font html类允许您指定字体大小 因此 要创建字体 您可以执行以下操作 Font f
  • 当行突出显示时设置 cellrenderertext 前景色

    当我有一个gtk CellRendererText 我可以关联它的foreground用树存储的一列着色 并设置foreground set属性设置为 True 以更改该列中文本的颜色 但是 当选择具有彩色列的行时 其颜色会消失 并且与任何
  • getContext().getSystemService 错误

    所以我只是想在我的 getView 函数中膨胀一个视图 而 getContext 由于某种原因说它是未定义的 package com MTSUAndroid import com MTSUAndroid Alarm Settings Eff
  • 是否有类似于 C sscanf 的 VB6 函数?

    我正在尝试读取由以下形式的文本行组成的文件 first value 1352 2 second value 12 third value 32323 first value 1233 2 second value 22 third valu
  • 关闭 Numba 中的列表反射

    我正在尝试使用 Numba 加速我的代码 我传递给函数的参数之一是可变列表列表 当我尝试更改子列表之一时 出现此错误 在 nopython 模式管道中失败 步骤 nopython 模式后端 无法反映反射容器的元素 反射列表 反射列表 int
  • 在 TFS API 中,如何获取给定测试的完整类名?

    我有一个ITestCaseResult http msdn microsoft com en us library microsoft teamfoundation testmanagement client itestcaseresult
  • postgresql 多个子查询

    我手头有一项任务 要求我返回一个学生的详细信息 该学生参加了一位姓霍夫曼的老师所教的课程 但我陷入了困境 SELECT FROM Public Class WHERE tid SELECT tid FROM Public Tutor WHE
  • 在 MVC Web 应用程序中访问 profile.newproperty

    我最近问了这个问题如何保留匿名用户选择 例如 主题选择 https stackoverflow com questions 11706349 how to persist anon user selection ex theme selec
  • 将解析信息添加到 Robolectric 包管理器

    这个问题与我想做的非常相似 如何使用 Robolectric 隐藏 PackageManager https stackoverflow com questions 12902777 how can i shadow the package
  • $.when 不等待 Ajax 请求完成

    我想首先使用 Backbone js 渲染一个视图 该视图显示从服务器拉取的文章 然后 我想将其标记为 已见 并将未见消息的计数返回给路由器 因为它需要可供其他视图使用 所以在我的路由器中 我有 getArticle function id
  • 使用javascript在IE中设置cookie

    document cookie cookiename cookievalue 过期 星期一 12Jun2015 00 00 00 路径 我在 Internet Explorer 10 上运行此脚本 但它不在 2 个 IE 选项卡之间共享 c
  • Unity 2D Trail 渲染器碰撞

    我制作 2D unity 游戏 但我面临着我的游戏所依赖的一个主要问题 我将一个轨迹渲染器组件附加到我的播放器上 我需要的是使渲染器成为一个碰撞器 充当网格碰撞器我只是不知道是否可以使碰撞器呈现 2D 轨迹渲染器的形状 我在谷歌上搜索过 但
  • 将 StackExchange.Redis 客户端与 Redis 集群结合使用

    如何告诉 StackExchange Redis v1 0 481 它即将连接到 Redis 集群 v3 2 6 如果重要的话 而不仅仅是独立 复制实例 例如 当我使用 redis cli 时 我必须传递 c 标志以使其具有集群感知能力 S
  • 尝试修复 tkinter GUI 冻结问题(使用线程)

    我有一个 Python 3 x 报告创建器 它的 I O 限制非常大 由于 SQL 而不是 Python 以至于主窗口将 锁定 minutes在创建报告时 所需要的只是能够在 GUI 锁定时使用标准窗口操作 移动 调整大小 最小化 关闭等