saltor 2017-05-13 03:27 采纳率: 100%
浏览 1146
已结题

python tkinter多线程程序中listbox和scrollbar的问题

最近在使用tkinter写的一个多线程的程序的时候遇到一个问题。

这个程序有5个线程,每个线程都会去执行show函数,show函数是输出0至999到listbox上。

我在当线程要输出数据到listbox上时使用了线程锁,可是程序就卡在第一个线程上,应该是卡在listbox.update()这里。

程序的执行顺序是:点击start按钮,生成了5个线程,有一个线程获得了进入共享区的锁,其余线程等待。但是进入共享区的那个线程却一直没有释放锁,我跟踪的时候看到是执行了listbox.update()后就卡住了。

可是只有一个线程获得了更新listbox的权限,为什么会出现这种情况。

当我把输出到listbox的语句换成"print i"直接输出到控制台上时,程序却是正常运行的,那么也就是说是listbox的更新机制问题了。

我又发现当我把listbox中yscrollcommand给注释掉后,程序就可以运行,但是scrollbar就没有用了。

那么当listbox更新发生改变时,会调用yscrollcommand中的srocllbar.set函数,然后srollbar又会去调用它command里面的listbox.yview函数。那问题是不是出现在线程调用和listbox,srollbar回调函数之间呢,那要怎样改才能使程序正常运行。

程序代码如下:(主要是注释的地方)

# -*- coding: utf8 -*-
from Tkinter import *
import time
import threading

class APP():
    def __init__(self,master):
        self.frame = Frame(master,height=2,bd=1,relief=SUNKEN)
        self.frame.pack(fill=X)
        self.button = Button(self.frame,text="Start",width=10,height=1,command=self.test)
        self.button.pack(padx=10,pady=10)

        self.sb = Scrollbar(self.frame)
        self.sb.pack(side=RIGHT,fill=Y)        
        self.listbox = Listbox(self.frame,height=25,width=50)
        self.listbox.pack()
        #我发现把yscrollcommand给注释掉后多线程程序才能跑起来,但是scrollbar就没用了
        #----------------------------------------------------------------
        self.listbox['yscrollcommand'] = self.sb.set
        #----------------------------------------------------------------
        self.sb.config(command=self.listbox.yview)   

    def test(self):
        func(self)

def func(self):
    def show(self):
        global mutex
        for i in range(1000):
            if mutex.acquire(1):#线程锁,进入共享区
                #------------------------------------------------------------
                self.listbox.insert(END,str(i))
                self.listbox.see(self.listbox.index(END))
                self.listbox.update()
                #------------------------------------------------------------
                #问题应该是出在多线程和listbox的更新这一块,就是上面三句
                mutex.release()

    for i in range(5):
        thread = threading.Thread(target=show,args=(self,))
        thread.setDaemon(True)
        thread.start()

mutex=threading.Lock()
root = Tk()
app = APP(root)
root.mainloop()
  • 写回答

1条回答 默认 最新

  • cyy298 2020-01-16 12:28
    关注

    给listbox绑定变量
    var = StringVar()
    listvariable=var
    更新var.set(data)

    评论

报告相同问题?

悬赏问题

  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试
  • ¥20 问题请教!vue项目关于Nginx配置nonce安全策略的问题
  • ¥15 教务系统账号被盗号如何追溯设备
  • ¥20 delta降尺度方法,未来数据怎么降尺度
  • ¥15 c# 使用NPOI快速将datatable数据导入excel中指定sheet,要求快速高效
  • ¥15 再不同版本的系统上,TCP传输速度不一致
  • ¥15 高德地图2.0 版本点聚合中Marker的位置无法实时更新,如何解决呢?
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题