Tkinter progressbar not working under Windows

时间:2015-10-06 08:32:38

标签: python windows user-interface tkinter scaling

I am writing an application that will be used under both Linux and Windows.

For the GUI I am using Tkinter, but I've got a problem when I try to run my program on Windows. On Linux, where I developed it, it works just fine.

I used a toplevel with a ttk progress bar to show the progress of loading data, before the program/GUI shows up. This progress bar is missing on Windows. It doesn't throw an error, it just seems to be not there. The place where it SHOULD be is transparent, so you can see the windows/desktop etc. behind the toplevel.

Any ideas why this occurs? Did anyone else had this problem?

Here's the code that calls the toplevel:

import Tkinter as tk
import ttk
import platform
import time

class Window(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.init_progbar()
        self.prog_data()
        self.top.destroy()

    #initializing progress bar, may be used with self.top
    def init_progbar(self):
        self.top = tk.Toplevel(self)
        self.top.frame = tk.Frame(self.top)
        self.top.frame.grid()
        self.top.frame.progbar = ttk.Progressbar(self.top.frame, \
            orient='horizontal', mode = 'determinate', length = '500')
        self.top.frame.progbar.grid()
        Window.center(self.top)

    #static method to center a toplevel window
    @staticmethod
    def center(toplevel, size=None):
        toplevel.update_idletasks()
        w = toplevel.winfo_screenwidth()
        h = toplevel.winfo_screenheight()
        if not size:
            size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
        x = w/2 - size[0]/2
        y = h/2 - size[1]/2
        toplevel.geometry("%dx%d+%d+%d" % (size + (x, y)))

    #dummy method - somethings done, then the value of the progress bar
    #is raised by 10
    def prog_data(self):
        for i in range(10):
            time.sleep(1)
            self.top.frame.progbar.step(10)
            self.top.update_idletasks()

def main():
    window = Window()
    window.mainloop()

if __name__=='__main__':
    main()

As I said earlier, this is running under Linux without any problem, it just doesn't work on Windows.

I tried it on two different Linux systems ( openSUSE and Ubuntu ) and on two different Computers running Windows, one Windows 7 and one Windows 10. Every time the same problem occurs - the progress bar is missing on Windows.

1 个答案:

答案 0 :(得分:1)

自己找到解决方案。问题是Windows和Linux下的执行似乎有点不同。

在您进入上面示例中的mainloop之前,Windows不会更新GUI。在Linux上处理这个问题显然是不同的,确保正确执行。

为了清楚起见,我重新编写了示例代码,因此可能会更清楚需要更改的内容。查看评论以获得进一步说明。

import Tkinter as tk
import ttk
import platform
import time

class Window(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.init_progbar()
        self.prog_data()
        self.top.destroy()

    #initializing progress bar, may be used with self.top.
    def init_progbar(self):
        #The frame here was unnecessary.
        self.top = tk.Toplevel(self)
        self.top.progbar = ttk.Progressbar(self.top, \
            orient='horizontal', mode = 'determinate', length = '500')
        self.top.progbar.grid()
        Window.center(self.top)

    #static method to center a toplevel window
    @staticmethod
    def center(toplevel, size=None):
        toplevel.update_idletasks()
        w = toplevel.winfo_screenwidth()
        h = toplevel.winfo_screenheight()
        if not size:
            size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
        x = w/2 - size[0]/2
        y = h/2 - size[1]/2
        toplevel.geometry("%dx%d+%d+%d" % (size + (x, y)))
        #This processes every pending geometry change and redraws the widget.
        self.update()

    #dummy method - somethings done, then the value of the progress bar
    #is raised by 10
    def prog_data(self):
        for i in range(10):
            time.sleep(1)
            self.top.frame.progbar.step(10)
            #Updates the whole GUI every time some data gets processed.
            self.update()

def main():
    window = Window()
    window.mainloop()

if __name__=='__main__':
    main()