学习打码 2023-05-02 15:58 采纳率: 0%
浏览 11

如何实时判断python os.stdout中是否有输出流?

我在用tkinter做一个进度窗口
用重定向将项目子模块程序内的打印输出到进度窗口的text控件内
目前存在的问题是:
进度窗口有进度条,但进度条卡顿,必须等到text控件内有输出内容后,窗口才能刷新,进度条才能动一下。

  • 写回答

1条回答 默认 最新

  • Py小郑 Python领域潜力新星 2023-05-02 17:28
    关注

    这个问题是因为Tkinter的GUI更新是单线程的,也就是说在执行打印输出时,GUI会被阻塞,直到输出完成才会进行刷新。因此,您需要将进度更新与打印输出分离,以避免GUI被阻塞。以下是一个可能的解决方案:

    1. 在进度窗口中创建一个Text控件和一个Scrollbar控件,用于显示和滚动文本。
    2. 将进度窗口作为一个独立的线程,在该线程中实时更新进度条。
    3. 在主线程中执行子模块程序,并将其输出重定向到一个队列中。
    4. 在进度窗口线程中循环读取该队列,并将其内容追加到Text控件中。

    下面是一个简单的示例代码:

    import threading
    import queue
    import time
    import tkinter as tk
    
    
    class ProgressWindow(threading.Thread):
        def __init__(self):
            super().__init__()
            self.queue = queue.Queue()
            self.progress = 0
            self.root = tk.Tk()
            self.text = tk.Text(self.root)
            self.text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
            self.scrollbar = tk.Scrollbar(self.root)
            self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
            self.text.config(yscrollcommand=self.scrollbar.set)
            self.scrollbar.config(command=self.text.yview)
            self.progressbar = tk.Canvas(self.root, width=200, height=20, bg='white')
            self.progressbar.pack(side=tk.BOTTOM, padx=5, pady=5)
            self.start()
    
        def run(self):
            while self.progress < 100:
                self.progressbar.delete("all")
                self.progressbar.create_rectangle(0, 0, self.progress * 2, 20, fill="green")
                self.root.update()
                time.sleep(0.1)
    
        def append_text(self, text):
            self.queue.put(text)
    
        def update_progress(self, progress):
            self.progress = progress
    
        def show(self):
            self.root.mainloop()
    
    
    class RedirectText:
        def __init__(self, text_ctrl):
            self.output = text_ctrl
    
        def write(self, string):
            self.output.append_text(string)
    
    
    def run_submodule():
        for i in range(10):
            print("Output from submodule: {}".format(i))
            time.sleep(1)
    
    
    if __name__ == "__main__":
        window = ProgressWindow()
        sys.stdout = RedirectText(window.text)
        window.show()
        t = threading.Thread(target=run_submodule)
        t.start()
        for i in range(10):
            window.update_progress((i + 1) * 10)
            time.sleep(1)
        t.join()
        window.update_progress(100)
    

    在这个示例代码中,我们创建了一个ProgressWindow类来表示进度窗口。该类继承自threading.Thread类,并在构造函数中创建了一个Text控件和一个Scrollbar控件,以及一个进度条的Canvas控件。在run()方法中,我们循环更新进度条的进度,并使用self.root.update()方法实时刷新GUI。

    评论

报告相同问题?

问题事件

  • 创建了问题 5月2日

悬赏问题

  • ¥15 xcode开发的macos应用,如何使窗口居中显示?
  • ¥20 统信uos升级apt后启动失败
  • ¥15 求指导储层饱和度及含水率测井解释
  • ¥200 建三维地震工区写入sgy到指定目录
  • ¥30 靶向捕获测序探针设计自学
  • ¥15 写代码写代码单片机代码写代码写数字按键代码
  • ¥15 django按照距离进行排序
  • ¥15 (标签-微信|关键词-微信公众号)
  • ¥15 matlab中mjs用不了
  • ¥15 Ios抖音直播的时候如何添加自定义图片在直播间!