gpt4 book ai didi

python - 尝试修复tkinter GUI卡住(使用线程)

转载 作者:行者123 更新时间:2023-12-01 08:40:29 25 4
gpt4 key购买 nike

我有一个Python 3.x报表创建器,该报表创建器受I/O约束(由于SQL,而不是python),因此在创建报表时主窗口将“锁定”几分钟。

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

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

这样做的最简单/最简单的方法是什么(=对现有代码的干扰最小)-理想情况下,应以与Python> = 3.2.2兼容的方式以及跨平台的方式(即至少在Windows和linux上可以使用)进行操作。

下面的所有内容都是支持性信息,可以更详细地说明问题,尝试的方法以及遇到的一些细微问题。

要考虑的事情:

  • 用户选择他们的报告,然后在主窗口上按“创建报告”按钮(当实际工作开始并发生冻结时)。完成所有报告后,报告创建代码将显示一个(顶级)“完成”窗口。关闭此窗口将启用主窗口中的所有内容,从而使用户可以退出程序或创建更多报告。
  • 添加了20181129:显然可以以随机间隔(相隔几秒钟)移动窗口。
  • 除了显示“完成”窗口外,报告创建代码不以任何方式涉及GUI或tkinter。
  • 由报表创建代码生成的某些数据必须出现在“完成”窗口中。
  • 没有理由“并行化”报告的创建,尤其是因为使用相同的SQL Server和数据库来创建所有报告。
  • 如果它影响解决方案:随着每个报告的创建,我最终将需要在GUI上显示报告名称(现在显示在控制台上)。
  • 第一次使用python进行线程/子处理,但对其他语言都熟悉。
  • 添加了20181129:开发环境是Win 10上使用Eclipse Oxygen(pydev插件)的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保持冻结状态,“Done”窗口(现在由新线程调用)从不出现。这使用户陷入困境,无法做任何事情,并且
    想知道发生了什么(如果有的话)(这就是为什么我想在创建文件名时在GUI上显示它们的原因)。

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

    我也尝试使用
    from multiprocessing import Process

    ReportCreationProcess = Process( target = DoChosenReports )
    ReportCreationProcess.start()

    但这与主程序“if(__name__ =='__main__):'”的行为相违背。

    添加了20181129:刚刚发现了“waitvariable”通用窗口小部件方法(请参阅 http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html)。基本思想是将创建报告代码作为由该方法控制的永久执行线程(守护进程?)启动(执行由GUI上的“执行报告”按钮控制)。

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

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

    最佳答案

    您将需要两个函数:第一个封装您程序的长时间运行的工作,第二个创建一个处理第一个函数的线程。如果您需要线程在用户仍在运行时关闭程序时立即停止线程(不建议),请使用daemon标志或调查 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()

    关于python - 尝试修复tkinter GUI卡住(使用线程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53525746/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com