a200710716
saltor
采纳率85.7%
2017-05-13 03:27

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

5
最近在使用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 cyy298 1年前

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

    点赞 评论 复制链接分享

相关推荐