我有一个 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 上)