Display toplevel tk at the begining of a function

风格不统一 提交于 2021-01-29 14:15:42

问题


I have an application where I want to display a progress bar during calcul. So, there is a button on my app to run a function and also display the progress bar, but the child window only appears at the end of the calcul.

To reproduce this you can try the code below :

import tkinter as tk
from tkinter import ttk as ttk


class MainApplication:

    def __init__(self, master):
        self.master = master
        self.button_start = tk.Button(
            self.master, text='Begin', command=self.upload_button)
        self.button_start.place(relx=0.5, rely=0.5)


    def upload_button(self):
        newWindow = tk.Toplevel(self.master)
        newWindow.title("Chargment...")
        newWindow.geometry("400x70")
        # A Label widget to show in toplevel
        ttk.Label(newWindow, text="Please wait...").pack()
        pb = ttk.Progressbar(newWindow, length=300)
        pb.pack()
        pb.start(10)
        for i in range(90000):
            print(i)


window = tk.Tk()
window.title("my title")
MainApplication(window)
window.mainloop()

EDIT

I have tried to use threading and after to resolve my problem but i get stuck. I don't know how to replace the after method by some calcul in python using pandas. I can't just put one value for the delay in the after method because the delay could be different if the final user work on a small table or a bigger one.

import tkinter as tk
from PIL import Image, ImageTk
import threading
import time
from tkinter import messagebox
from itertools import count


class GIFLabel(tk.Label):
    """a label that displays images, and plays them if they are gifs"""
    def load(self, im):
        if isinstance(im, str):
            im = Image.open(im)
        self.loc = 0
        self.frames = []
    try:
        for i in count(1):
            self.frames.append(ImageTk.PhotoImage(im.copy().resize((20,20))))
            im.seek(i)
    except EOFError:
        pass

    try:
        self.delay = im.info['duration']
    except:
        self.delay = 100

    if len(self.frames) == 1:
        self.config(image=self.frames[0])
    else:
        self.next_frame()

def unload(self):
    self.config(image="")
    self.frames = None

def next_frame(self):
    if self.frames:
        self.loc += 1
        self.loc %= len(self.frames)
        self.config(image=self.frames[self.loc])
        self.after(self.delay, self.next_frame)





class MainApplication:

def __init__(self, master):
    self.master = master
    self.button_start = tk.Button(self.master, text='Begin', command=self.upload_button)
    self.button_start.place(relx=0.5, rely=0.5)
    self.loading = GIFLabel(self.master)
    self.loading.place(relx=0.5, rely=0.7)
    self.loading.load('loading.gif')
    
def wait_generate(self):
    if self.update_Thread.isAlive():
        self.master.after(500, self.wait_generate)

    else:
        self.loading.unload()
        self.loading.load('ok.png')
        messagebox.showinfo("Complete", "Report generation completed!")
        


def upload_button(self):
    self.update_Thread = threading.Thread(target=time.sleep, args=(5,))
    self.update_Thread.start()
    self.wait_generate()


window = tk.Tk()
window.title("my title")
MainApplication(window)
window.mainloop()

回答1:


When you run through your for loop, the tkinter window doesn't get a chance to automatically update (normally through mainloop).

There are two options

  1. Run the for loop in a separate Thread (you can't run tkinter in a separate thread though)
  2. Manually update the window in your for loop

You can research how to use threads, but the simplest option here is to include either of the following in your for loop:

self.master.update() or newWindow.update()

This manually updates the window, meaning that the progress bar can be updated and become visible.

It should look like this:

for i in range(90000):
    print(i)

    # you can use
    self.master.update()
    # or
    newWindow.update()


来源:https://stackoverflow.com/questions/63113382/display-toplevel-tk-at-the-begining-of-a-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!