【问题标题】:freezing gui while socket在套接字时冻结 gui
【发布时间】:2017-07-24 03:48:48
【问题描述】:

我正在构建一个小型 gui 应用程序,允许用户 从服务器下载文件。它主要用于套接字和 tkinter。 但是当我下载一个文件(例如一部电影)时,它需要一些时间,例如 5 分钟。在那个时候,我想要一个进度条,它将开始循环直到文件完全下载。但是当客户端使用sock.recv逐行获取文件数据时, 所有的 gui 程序都冻结了! 所以因为进度条不能移动, 我不能按任何按钮。 所以我的问题是 - 我该如何解决?意味着gui应用程序在从服务器获取数据时不会被堆栈,然后我可以让进度条工作。 非常感谢你们。

【问题讨论】:

  • 你必须使用后台线程。

标签: python sockets user-interface


【解决方案1】:

在这里,我尝试描述(主要是伪代码)如何实现带有进度条的非阻塞下载功能。

希望对你有帮助。

def update_progress(percentage):
    # update your progress bar in GUI

def download(callback):
    # implement your download function
    # check the full size of the file to be downloaded.
    # try to download a reasonable amount at once
    # call callback with percentage that you have downloaded to update GUI

    total = 1000000 # get total size of the file to be downloaded.
    current = 0
    block_size = 1000 # i.e., 1 KB

    while True:
        # do required operations to download data of block_size amount
        # example: sock.recv(block_size)
        current += block_size

        # calculate downloaded percentage
        percentage = (block_size * 100) / total # you may add precision if you prefer

        # call the callback function to update GUI based on the downloaded percentage
        callback(percentage)

        # check if download completed
        if current >= total:
            break

def start_download(): # bind this function to your button's click on GUI.
    # import threading

    # create a thread to execute download
    # see how 'update_progress' is passed as an argument
    thread = threading.Thread(target=download, args=[update_progress])
    thread.start()

    # execution will not be blocked here as the thread runs in the background.
    # so, any code here will run without waiting for download to be completed.

【讨论】:

    【解决方案2】:

    感谢你们的帮助,特别是对你们ohannes,我在后台使用 线程类,这是代码:(您需要将 'root' 更改为 tkinter 窗口的名称)

    class ThreadedClient(threading.Thread):
        def __init__(self, queue, fcn):
            threading.Thread.__init__(self)
            self.queue = queue
            self.fcn = fcn
        def run(self):
            time.sleep(1)
            self.queue.put(self.fcn())
    
    def spawnthread(fcn):
        thread = ThreadedClient(queue, fcn)
        thread.start()
        periodiccall(thread)
    
    def periodiccall(thread):
        if(thread.is_alive()):
            root.After(100, lambda: periodiccall(thread))
            #END
    

    【讨论】:

      猜你喜欢
      • 2022-08-05
      • 2013-02-24
      • 1970-01-01
      • 2018-06-05
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      • 2013-01-16
      相关资源
      最近更新 更多