zoukankan      html  css  js  c++  java
  • python treeview 多线程下表格插入速度慢解决方法

    python treeview 多线程下表格插入速度慢解决方法

    最近用tk得treeview做了个表格来展视数据

    输入id,查询接口数据,然后显示数据

    按照之前得操作,搜索按钮绑定一个单独得线程进行操作,这样界面不会卡死,毕竟查询网络接口是个耗时操作

    大概是这样得代码

    from tkinter import ttk
    from tkinter import *
    import random
    import threading
    import time
    
    class MyThread(threading.Thread):
        def __init__(self, func, *args):
            super(MyThread, self).__init__()
            self.func = func
            self.args = args
            self.setDaemon(True)
            self.start()  # 在这里开始
    
        def run(self):
            self.func(*self.args)
    
    def add_row():
    #模拟网络请求 time.sleep(3) for i in range(300): treeview.insert('', i, values=( i, random.randint(1,10), random.randint(1,10), random.randint(1,10), random.randint(1,10), random.randint(1,10))) def del_table(): [treeview.delete(item) for item in treeview.get_children()] root = Tk() column_names = [ f'列{x}' for x in range(6)] columns = list('abcdefghijklmnopqrstuvwxyz'[:len(column_names)]) ybar = Scrollbar(root, orient='vertical') treeview = ttk.Treeview(root, height=18, show="headings", columns=columns, yscrollcommand=ybar.set) # 表格 ybar['command'] = treeview.yview ybar.pack(side=RIGHT, fill=BOTH) for num, column in enumerate(columns): treeview.column(column, width=100, anchor='center') treeview.heading(column, text=column_names[num]) treeview.pack(fill=BOTH) newb = ttk.Button(root, text='添加行', width=20, command=lambda: MyThread(add_row, )) newb.pack(fill=BOTH) newb = ttk.Button(root, text='删除表格', width=20, command=del_table) newb.pack(fill=BOTH) root.mainloop() # 进入消息循环

     点击添加行按钮,3秒后可以看出在插入行,300行要插入个10来秒,插入得时候可以看到滚动条滑块再不停得变小

    如果不使用线程,按钮直接绑定函数

    比如

    newb = ttk.Button(root, text='添加行', width=20, command=add_row)

    那么在3秒的休眠中,界面会卡死,无法操作
    不过插入行却是一瞬间的事情,几乎1秒不到就插入了300多行
    网上查了下,说是不建议在多线程里面操作界面,会出现并发操作问题
    而且这个也证明了在线程中进行大量界面修改速度是非常慢的

    那么这个解决办法就是不在线程中插入表格,再ui的主线程中插入表格,这样就能做到快速插入
    使用工具是queue列队,
    还有tk中的after方法,TKinter的root下有个after方法, 这个方法是个定时方法,用途是GUI启动后定时执行一个方法,如果我们在被after调用的方法里再次调用这个after方法,
    就可以实现一个循环效果,但这个循环不像while那样会阻塞住主线程


    完整代码如下

    from tkinter import ttk
    from tkinter import *
    import random
    import threading
    import time
    import queue
    
    
    table_queue = queue.Queue()
    
    class MyThread(threading.Thread):
        def __init__(self, func, *args):
            super(MyThread, self).__init__()
            self.func = func
            self.args = args
            self.setDaemon(True)
            self.start()  # 在这里开始
    
        def run(self):
            self.func(*self.args)
    
    def add_row():
        if not table_queue.empty():
            rows = table_queue.get()
            for row in rows:
                treeview.insert('', row[0], values=(
                    row[0],
                    row[1],
                    row[2],
                    row[3],
                    row[4],
                    row[5]))
        root.after(100, add_row) #运行完后再次加入到循环中
    
    def do_add():
        #模拟网络请求耗时操作
        time.sleep(3)
        rows = [
            [x,random.randint(1,10),random.randint(1,10),random.randint(1,10),random.randint(1,10),random.randint(1,10)]
            for x in range(300)
        ]
        table_queue.put(rows)
    
    
    
    
    def del_table():
        [treeview.delete(item) for item in treeview.get_children()]
    
    
    
    root = Tk()
    
    root.after(100, add_row) #启动添加表格操作(不会阻塞主线程)
    
    column_names = [ f'列{x}' for x in range(6)]
    columns = list('abcdefghijklmnopqrstuvwxyz'[:len(column_names)])
    
    ybar = Scrollbar(root, orient='vertical')
    
    treeview = ttk.Treeview(root, height=18, show="headings", columns=columns, yscrollcommand=ybar.set)  # 表格
    ybar['command'] = treeview.yview
    ybar.pack(side=RIGHT, fill=BOTH)
    
    for num, column in enumerate(columns):
        treeview.column(column, width=100, anchor='center')
        treeview.heading(column, text=column_names[num])
    
    treeview.pack(fill=BOTH)
    
    newb = ttk.Button(root, text='添加行', width=20, command=lambda: MyThread(do_add, ))
    newb.pack(fill=BOTH)
    
    newb = ttk.Button(root, text='删除表格', width=20, command=del_table)
    newb.pack(fill=BOTH)
    
    root.mainloop()  # 进入消息循环
    

      

  • 相关阅读:
    HDU 2047 阿牛的EOF牛肉串
    HDU 2015 偶数求和
    HDU 2029 算菜价
    HDU 2028 Lowest Common Multiple Plus
    动态函数库设计
    静态函数库设计
    Linux编程规范
    Linux应用程序地址布局
    Core Dump 程序故障分析
    W-D-S-UART编程
  • 原文地址:https://www.cnblogs.com/darkspr/p/14108201.html
Copyright © 2011-2022 走看看