开发者

Tkinter progress bar/window not responding when moved

开发者 https://www.devze.com 2023-02-07 19:40 出处:网络
I have borrowed a progress bar from here that I would like to adapt work in my program with global variables.Here is the code for reference:

I have borrowed a progress bar from here that I would like to adapt work in my program with global variables. Here is the code for reference:

import Tkinter

class Meter(Tkinter.Frame):
    def __init__(self, master, width=300, height=20, bg='white', fillcolor='orchid1',\
                 value=0.0, text=None, font=None, textcolor='black', *args, **kw):
        Tkinter.Frame.__init__(self, master, bg=bg, width=width, height=height, *args, **kw)
        self._value = value

        self._canv = Tkinter.Canvas(self, bg=self['bg'], width=self['width'], height=self['height'],\
                                    highlightthickness=0, relief='flat', bd=0)
        self._canv.pack(fill='both', expand=1)
        self._rect = self._canv.create_rectangle(0, 0, 0, self._canv.winfo_reqheight(), fill=fillcolor,\
                                                 width=0)
        self._text = self._canv.create_text(self._canv.winfo_reqwidth()/2, self._canv.winfo_reqheight()/2,\
                                            text='', fill=textcolor)
        if font:
            self._canv.itemconfigure(self._text, font=font)

        self.set(value, text)
        self.bind('<Configure>', self._update_coords)

    def _update_coords(self, event):
        '''Updates the position of the text and rectangle inside the canvas when the size of
        the widget gets changed.'''
        # looks like we have to call update_idletasks() twice to make sure
        # to get the results we expect
        self._canv.update_idletasks()
        self._canv.coords(self._text, self._canv.winfo_width()/2, self._canv.winfo_height()/2)
        self._canv.coords(self._rect, 0, 0, self._canv.winfo_width()*self._value, self._canv.winfo_height())
        self._canv.update_idletasks()

    def get(self):
        return self._value, self._canv.itemcget(self._text, 'text')

    def set(self, value=0.0, text=None):
        #make the value failsafe:
        if value < 0.0:
            value = 0.0
        elif value > 1.0:
            value = 1.0
        self._value = value
        if text == None:
            #if no text is specified use the default percentage string:
            text = str(int(round(100 * value))) + ' %'
        self._canv.coords(self._rect, 0, 0, self._canv.winfo_width()*value, self._canv.winfo_height())
        self._canv.itemconfigure(self._text, text=text)
        self._canv.update_idletasks()

##-------------demo code--------------------------------------------##

def _demo(meter, value):
    meter.set(value)
    if value < 1.0:
        value = value + 0.005
        meter.after(50, lambda: _demo(meter, value))
    else:
        meter.set(value, 'Demo successfully finished')

if __name__ == '__main__':
    root = Tkinter.Tk(className='meter demo')
    m = Meter(root, relief='ridge', bd=3)
    m.pack(fill='x')
    m.set(0.0, 'Starting demo...')
    m.after(1000, lambda: _demo(m, 0.0))
    root.mainloop()

This code and demo work great, but when I make the following changes so I can test how I would want to impliment it into my code, the progress window becomes unresponsive and turns blank whenever I move it or activate another window.

##-------------demo code--------------------------------------------##

def some_fct(m):开发者_运维知识库
    global count
    i = 0
    while i < 5:
        count = count + 1
        sleep(2)
        m.set(float(count) / total)
        i = i + 1

def other_fct(m):
    global count
    i = 0
    while i < 5:
        count = count + 1
        sleep(2)
        m.set(float(count) / total)
        i = i + 1

if __name__ == '__main__':
    global count
    global total
    count = 0
    total = 10
    root = Tkinter.Tk(className='meter demo')
    m = Meter(root, relief='ridge', bd=3)
    m.pack(fill='x')
    m.set(0.0, 'Starting meter')
    some_fct(m)
    other_fct(m)
    root.mainloop()

Any idea what is going on here and why it becomes unresponsive? Does it have anything to do with the global variable being used? It seems to work "ok" when it's not moved, but it's definitely not the same.


some_fct and other_fct both sleep for 10 seconds each, so the app will be unresponsive for at least 20 seconds when it starts up since those sleeps all happen before mainloop is called. Are you saying that even after those 20 seconds the app is unresponsive, or are you asking why it's unresponsive for the first 20 seconds?

Tkinter is single threaded, which means that any time you put in a sleep it's not going to be able to service events for the duration of the sleep. It is this servicing of events that defines "responsiveness".


Here is the code I used to get what I wanted:

##-------------demo code--------------------------------------------##

def count_numbers(number):
    i = 0
    while i < number:
        i = i + 1

def some_fct():
    global count
    i = 0
    while i < 5:
        count = count + 1
        count_numbers(5000000)
        i = i + 1

def other_fct():
    global count
    i = 0
    while i < 5:
        count = count + 1
        count_numbers(5000000)
        i = i + 1

def do_stuff():
    some_fct()
    other_fct()

def update_progress(m):
    value = float(count) / total
    if value < 1.0:
        m.set(value)
        m.after(500, lambda: update_progress(m))
    else:
        m.set(value, 'Process Completed')

if __name__ == '__main__':
    global count
    global total
    count = 0
    total = 10
    root = Tkinter.Tk(className='meter demo')
    m = Meter(root, relief='ridge', bd=3)
    m.pack(fill='x')
    m.set(0.0, 'Starting meter')    
    m.after(50, lambda: update_progress(m))
    thread.start_new_thread(do_stuff, () )
    root.mainloop()
0

精彩评论

暂无评论...
验证码 换一张
取 消