2016-09-15 44 views
0

我在寫一個小應用程序來複制一些文件。我做了幾乎所有我想要的東西,但有三件事:tkinter不能正常工作的進度條

1)在複製選項處於運動狀態時移動的進度條。我可以顯示它,但它不會反應。

我使用它來顯示它:

self.p = ttk.Progressbar(self, orient=HORIZONTAL, length=300, mode='indeterminate') 
self.p.grid(row=5) 

,然後啓動它在另一個DEF這是在擠壓按鈕的按下叫:

self.p.start() 

shutil.copytree(self.source_direcotry0, self.cam0) 
shutil.copytree(self.source_direcotry1, self.cam1) 
shutil.copytree(self.source_direcotry2, self.cam2) 

self.p.stop() 

不幸發生複製,但酒吧根本不動。

2)第二個問題是連接到我的應用程序窗口的底部顯示的信息欄:

self.status = Label(self.master, text="Waiting for process to start...", bd=1, relief=SUNKEN, anchor=W) 
self.status.pack(side=BOTTOM, fill=X) 

,然後在相同的複製DEF被稱爲在它開始的時候我有這個:

self.status['text'] = "Files are being copyied, have patience ;)".format(self.status) 

且狀態沒有改變這是奇怪的是在這個高清結束時,我也有同樣的命令來改變現狀,這一件作品:

self.status['text'] = "Files have been copyied".format(self.status) 

3)我似乎無法附上一張照片我已經檢查過各種不同的選項,但它們都不起作用,這裏介紹的一個看起來像試圖顯示某些東西(窗口變大),但圖片不可見:

self.img = ImageTk.PhotoImage(Image.open("az.png")) 
self.panel = Label(self, image=self.img, bg="#E6E6E6") 
self.display = self.img 
self.panel.grid(row=8) 

我有點不確定它爲什麼發生這樣的,以防萬一,也爲更多的信息,我在這裏張貼的完整代碼:

from tkinter import * 
from tkinter import ttk 
import re 
from tkinter import messagebox 
from tkinter import filedialog 
import ntpath 
import os 
import shutil 
import tkinter.filedialog as fdialog 
from send2trash import send2trash 
from PIL import Image, ImageTk 

#os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''') 


# Here, we are creating our class, Window, and inheriting from the Frame 
# class. Frame is a class from the tkinter module. (see Lib/tkinter/__init__) 

class Window(Frame): 

    # Define settings upon initialization. Here you can specify 
    def __init__(self, master=None): 

     # parameters that you want to send through the Frame class. 
     Frame.__init__(self, master, bg="#E6E6E6") 

     #reference to the master widget, which is the tk window     
     self.master = master 

     #with that, we want to then run init_window, which doesn't yet exist 
     self.init_window() 

    def copyy(self): 

     self.status['text'] = "Files are being copyied, have patience ;)".format(self.status) 


     self.source_direcotry0= '/Volumes/CAM0/DCIM/100HDDVR' 
     self.source_direcotry1= '/Volumes/CAM1/DCIM/100HDDVR' 
     self.source_direcotry2= '/Volumes/CAM2/DCIM/100HDDVR' 
     self.source_direcotry3= '/Volumes/CAM3/DCIM/100HDDVR' 
     self.source_direcotry4= '/Volumes/CAM4/DCIM/100HDDVR' 
     self.source_direcotry5= '/Volumes/CAM5/DCIM/100HDDVR' 
     self.source_direcotry6= '/Volumes/CAM6/DCIM/100HDDVR' 
     self.source_direcotry7= '/Volumes/CAM7/DCIM/100HDDVR' 
     self.source_direcotry8= '/Volumes/CAM8/DCIM/100HDDVR' 
     self.source_direcotry9= '/Volumes/CAM9/DCIM/100HDDVR' 
     self.source_direcotry10= '/Volumes/CAM10/DCIM/100HDDVR' 
     self.source_direcotry11= '/Volumes/CAM11/DCIM/100HDDVR' 

     self.path0="recording/CAM0" 
     self.path1="recording/CAM1" 
     self.path2="recording/CAM2" 
     self.path3="recording/CAM3" 
     self.path4="recording/CAM4" 
     self.path5="recording/CAM5" 
     self.path6="recording/CAM6" 
     self.path7="recording/CAM7" 
     self.path8="recording/CAM8" 
     self.path9="recording/CAM9" 
     self.path10="recording/CAM10" 
     self.path11="recording/CAM11" 

     self.cam0=os.path.join(self.Destination.get(), self.path0) 
     self.cam1=os.path.join(self.Destination.get(), self.path1) 
     self.cam2=os.path.join(self.Destination.get(), self.path2) 
     self.cam3=os.path.join(self.Destination.get(), self.path3) 
     self.cam4=os.path.join(self.Destination.get(), self.path4) 
     self.cam5=os.path.join(self.Destination.get(), self.path5) 
     self.cam6=os.path.join(self.Destination.get(), self.path6) 
     self.cam7=os.path.join(self.Destination.get(), self.path7) 
     self.cam8=os.path.join(self.Destination.get(), self.path8) 
     self.cam9=os.path.join(self.Destination.get(), self.path9) 
     self.cam10=os.path.join(self.Destination.get(), self.path10) 
     self.cam11=os.path.join(self.Destination.get(), self.path11) 

     self.p.start() 

     shutil.copytree(self.source_direcotry0, self.cam0) 
     shutil.copytree(self.source_direcotry1, self.cam1) 
     shutil.copytree(self.source_direcotry2, self.cam2) 
     # shutil.copytree(self.source_direcotry3, self.cam3) 
     # shutil.copytree(self.source_direcotry4, self.cam4) 
     # shutil.copytree(self.source_direcotry5, self.cam5) 
     # shutil.copytree(self.source_direcotry6, self.cam6) 
     # shutil.copytree(self.source_direcotry7, self.cam7) 
     # shutil.copytree(self.source_direcotry8, self.cam8) 
     # shutil.copytree(self.source_direcotry9, self.cam9) 
     # shutil.copytree(self.source_direcotry10, self.cam10) 
     # shutil.copytree(self.source_direcotry11, self.cam11) 

     self.p.stop() 

     self.status['text'] = "Files have been copyied".format(self.status) 

    def deletee(self): 
     send2trash('/Volumes/CAM0/DCIM') 
     send2trash('/Volumes/CAM1/DCIM') 
     send2trash('/Volumes/CAM2/DCIM') 
     # send2trash('/Volumes/CAM3/DCIM') 
     # send2trash('/Volumes/CAM4/DCIM') 
     # send2trash('/Volumes/CAM5/DCIM') 
     # send2trash('/Volumes/CAM6/DCIM') 
     # send2trash('/Volumes/CAM7/DCIM') 
     # send2trash('/Volumes/CAM8/DCIM') 
     # send2trash('/Volumes/CAM9/DCIM') 
     # send2trash('/Volumes/CAM10/DCIM') 
     # send2trash('/Volumes/CAM11/DCIM') 

     self.status['text'] = "Files have been moved to trash".format(self.status) 


    def client_exit(self): 
     exit() 

    def about_popup(self): 
     messagebox.showinfo("About", "This is software used to copy or delete files in bulk from the Absolute Zero VR camera") 


    #Creation of init_window 
    def init_window(self): 

     self.Source=StringVar() 
     self.Destination=StringVar() 


     # changing the title of our master widget  
     self.master.title("AZ Data Extractor") 

     # allowing the widget to take the full space of the root window 
     self.pack(fill=BOTH, expand=1) 

     #Creating the menu 
     self.menubar = Menu(self.master) 

     #Creating submenues 
     self.filemenu = Menu(self.menubar, tearoff=0) 
     self.filemenu.add_command(label="Exit", command=root.quit) 
     self.menubar.add_cascade(label="File", menu=self.filemenu) 

     self.helpmenu = Menu(self.menubar, tearoff=0) 
     self.helpmenu.add_command(label="About", command=self.about_popup) 
     self.menubar.add_cascade(label="Help", menu=self.helpmenu) 

     #Displaying the menu 
     root.config(menu=self.menubar) 

     #Creating the intro label 
     l_instruction = Label(self, justify=CENTER, compound=TOP, text="Choose the destination for the copied files \n and press 'Go!' to start copyting", bg="#E6E6E6") 
     l_instruction.grid(columnspan=2, ipady=10) 

     l_instruction = Label(self, justify=CENTER, compound=TOP, text="Press 'Delete' to move all files \n from the camera to the trash", bg="#E6E6E6") 
     l_instruction.grid(row=6, columnspan=2, ipady=10) 

     # ttk.Style().configure('green/black.TButton', foreground='green', background='black') 
     #Creating the button 
     MyDestination=Entry(self, textvariable=self.Destination, bg="#E6E6E6") 
     MyDestination.grid(row=2, columnspan=2, ipady=10) 
     uploadButton = Button(self, text="Choose destination folder",command=lambda:self.Destination.set(fdialog.askdirectory())) 
     uploadButton.grid(row=3, columnspan=2, ipady=10) 
     goButton = Button(self, text="Go!",command=self.copyy) 
     goButton.grid(row=4, columnspan=2, ipady=10) 
     delButton = Button(self, text="Delete",command=self.deletee) 
     delButton.grid(row=7, columnspan=2, ipady=10) 

     self.p = ttk.Progressbar(self, orient=HORIZONTAL, length=300, mode='indeterminate') 
     self.p.grid(row=5) 

     self.img = ImageTk.PhotoImage(Image.open("az.png")) 
     self.panel = Label(self, image=self.img, bg="#E6E6E6") 
     self.display = self.img 
     self.panel.grid(row=8) 


     #resizing configuration 
     self.grid_columnconfigure(0,weight=1) 
     self.grid_columnconfigure(1,weight=1) 
     self.grid_rowconfigure(0,weight=1) 
     self.grid_rowconfigure(1,weight=1) 
     self.grid_rowconfigure(2,weight=1) 
     self.grid_rowconfigure(3,weight=1) 
     self.grid_rowconfigure(4,weight=1) 
     self.grid_rowconfigure(5,weight=1) 
     self.grid_rowconfigure(6,weight=1) 
     self.grid_rowconfigure(7,weight=1) 
     self.grid_rowconfigure(8,weight=1) 
     self.grid_rowconfigure(9,weight=1) 
     self.grid_rowconfigure(10,weight=1) 

     #status Bar 
     self.status = Label(self.master, text="Waiting for process to start...", bd=1, relief=SUNKEN, anchor=W) 
     self.status.pack(side=BOTTOM, fill=X) 


# root window created. Here, that would be the only window, but you can later have windows within windows. 
root = Tk() 
root.resizable(width=False,height=False); 
# root.configure(background='black'); 
# fm = Frame(root, width=300, height=200, bg="blue") 
# fm.pack(side=TOP, expand=NO, fill=NONE) 
#root.geometry("230x340") 



#creation of an instance 
app = Window(root) 

#mainloop 
root.mainloop() 

編輯: 剛因爲在此期間出現的另一個問題我似乎無法改變按鈕的底色和輸入字段周圍的框架。我讀到它可能是因爲使用MacOS平臺,可以嗎?任何解決方法?

+0

EDIT2:我已經找到一種方法,使圖片的工作和按鈕的背景與: 圖片: 渲染=光象(文件=「az.gif」 ) IMG =標籤(個體,圖像渲染=,BG = 「#E6E6E6」) img.image =渲染 img.grid(行= 8) 和按鈕加入 「highlightbackground」: goButton =按鈕( self,text =「Go!」,command = self.copyy,highli ghtbackground =「#E6E6E6」) 但我仍然無法弄清楚這個進度條,根本沒有提示? – Bart

+0

您應該在調用'self.p.start()'後嘗試在新線程上啓動複製功能。複製可能會阻止UI線程爲進度條設置動畫。 – Joules

+0

我嘗試過使用線程,但是我無法使它工作,甚至在我使用線程時文件不會被複制。可能我錯誤地實現了它,但我找不到如何正確執行它的方法。 'self.p.start() root.update_idletasks() 對於x在範圍(12): 噸= threading.Thread(目標= self.copyy2) t.deamon =真 t.start() self.p.stop()' 然後所有的'shutil.copytree(self.source_direcotry0,self.cam0)'都被移動到新的名爲'copyy2'的def中。 – Bart

回答

0

我壓縮了我在我的舊項目中工作的加載欄。我弄明白的唯一方法是在新線程中調用處理調用的進度條,並將該線程中的工作密集函數調用到另一個新線程中。

有一個單獨的線程處理用戶界面線程以外的用戶界面元素,包括啓動和停止進度條是不好的做法;然而它確實有效,並且我一直在使用這個項目在幾個月內用零問題進行相當繁重的處理。

這裏進度條是工作在一個小的腳本,在W10使用Python 3.5.2 64位

from tkinter import * 
import tkinter.ttk as ttk 
import threading 
import time 

class Main_Frame(object): 
    def __init__(self, top=None): 
     # save root reference 
     self.top = top 
     # set title bar 
     self.top.title("Loading bar example") 

     # start button calls the "initialization" function bar_init, you can pass a variable in here if desired 
     self.start_button = ttk.Button(top, text='Start bar', command=lambda: self.bar_init(2500)) 
     self.start_button.pack() 

     # the progress bar will be referenced in the "bar handling" and "work" threads 
     self.load_bar = ttk.Progressbar(top) 
     self.load_bar.pack() 

     # run mainloop 
     self.top.mainloop() 

    def bar_init(self, var): 
     # first layer of isolation, note var being passed along to the self.start_bar function 
     # target is the function being started on a new thread, so the "bar handler" thread 
     self.start_bar_thread = threading.Thread(target=self.start_bar, args=(var,)) 
     # start the bar handling thread 
     self.start_bar_thread.start() 

    def start_bar(self, var): 
     # the load_bar needs to be configured for indeterminate amount of bouncing 
     self.load_bar.config(mode='indeterminate', maximum=100, value=0) 
     # 8 here is for speed of bounce 
     self.load_bar.start(8) 
     # start the work-intensive thread, again a var can be passed in here too if desired 
     self.work_thread = threading.Thread(target=self.work_task, args=(var,)) 
     self.work_thread.start() 
     # close the work thread 
     self.work_thread.join() 
     # stop the indeterminate bouncing 
     self.load_bar.stop() 
     # reconfigure the bar so it appears reset 
     self.load_bar.config(value=0, maximum=0) 

    def work_task(self, wait_time): 
     for x in range(wait_time): 
      time.sleep(0.001) 

if __name__ == '__main__': 
    # create root window 
    root = Tk() 
    # call Main_Frame class with reference to root as top 
    Main_Frame(top=root) 
+0

非常感謝您的幫助,我需要一段時間來消化並嘗試它,但如果再有疑問,我會回來。再次感謝! – Bart

+0

沒問題,如果你有任何問題可以隨時發表評論,我會盡力幫助你! :) – Joules

0

所以我用你的代碼,使礦山的改進和工程:)不幸的是有一個「但」。所以當文件被複制時,進度條很好地移動。在按下按鈕執行應對之後,複製開始之前還有相當長的延遲時間,這仍然不是完美的。一般用戶可能會開始懷疑程序崩潰了。我認爲線程開始的時候也有一些東西可以連接,但是我做了幾個組合,其中沒有一個改進了這個問題。我發佈完整的代碼,雖然它會更容易讓你看到發生了什麼。提前感謝@Joules!

下面是代碼:

from tkinter import * 
from tkinter import ttk 
import re 
from tkinter import messagebox 
from tkinter import filedialog 
import ntpath 
import os 
import shutil 
import tkinter.filedialog as fdialog 
from send2trash import send2trash 
from PIL import Image, ImageTk 
from threading import Thread 
import threading 


os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''') 


# Here, we are creating our class, Window, and inheriting from the Frame 
# class. Frame is a class from the tkinter module. (see Lib/tkinter/__init__) 

class Window(Frame): 

    # Define settings upon initialization. Here you can specify 
    def __init__(self, master=None): 

     # parameters that you want to send through the Frame class. 
     Frame.__init__(self, master, bg="#E6E6E6") 

     #reference to the master widget, which is the tk window     
     self.master = master 

     #with that, we want to then run init_window, which doesn't yet exist 
     self.init_window() 

    def bar_init(self): 
     # first layer of isolation, note var being passed along to the self.start_bar function 
     # target is the function being started on a new thread, so the "bar handler" thread 
     self.start_bar_thread = threading.Thread(target=self.copyy, args=()) 
     # start the bar handling thread 
     self.start_bar_thread.start() 

    def copyy(self): 
     root.update_idletasks() 
     self.status['text'] = "Files are being copyied, have patience ;)".format(self.status) 


     self.source_direcotry0= '/Volumes/CAM0/DCIM/100HDDVR' 
     self.source_direcotry1= '/Volumes/CAM1/DCIM/100HDDVR' 
     self.source_direcotry2= '/Volumes/CAM2/DCIM/100HDDVR' 
     self.source_direcotry3= '/Volumes/CAM3/DCIM/100HDDVR' 
     self.source_direcotry4= '/Volumes/CAM4/DCIM/100HDDVR' 
     self.source_direcotry5= '/Volumes/CAM5/DCIM/100HDDVR' 
     self.source_direcotry6= '/Volumes/CAM6/DCIM/100HDDVR' 
     self.source_direcotry7= '/Volumes/CAM7/DCIM/100HDDVR' 
     self.source_direcotry8= '/Volumes/CAM8/DCIM/100HDDVR' 
     self.source_direcotry9= '/Volumes/CAM9/DCIM/100HDDVR' 
     self.source_direcotry10= '/Volumes/CAM10/DCIM/100HDDVR' 
     self.source_direcotry11= '/Volumes/CAM11/DCIM/100HDDVR' 

     self.path0="recording/CAM0" 
     self.path1="recording/CAM1" 
     self.path2="recording/CAM2" 
     self.path3="recording/CAM3" 
     self.path4="recording/CAM4" 
     self.path5="recording/CAM5" 
     self.path6="recording/CAM6" 
     self.path7="recording/CAM7" 
     self.path8="recording/CAM8" 
     self.path9="recording/CAM9" 
     self.path10="recording/CAM10" 
     self.path11="recording/CAM11" 

     self.cam0=os.path.join(self.Destination.get(), self.path0) 
     self.cam1=os.path.join(self.Destination.get(), self.path1) 
     self.cam2=os.path.join(self.Destination.get(), self.path2) 
     self.cam3=os.path.join(self.Destination.get(), self.path3) 
     self.cam4=os.path.join(self.Destination.get(), self.path4) 
     self.cam5=os.path.join(self.Destination.get(), self.path5) 
     self.cam6=os.path.join(self.Destination.get(), self.path6) 
     self.cam7=os.path.join(self.Destination.get(), self.path7) 
     self.cam8=os.path.join(self.Destination.get(), self.path8) 
     self.cam9=os.path.join(self.Destination.get(), self.path9) 
     self.cam10=os.path.join(self.Destination.get(), self.path10) 
     self.cam11=os.path.join(self.Destination.get(), self.path11) 

     self.p.start(1) 


     self.work_thread = threading.Thread(target=self.copyy2, args=()) 
     self.work_thread.start() 
     self.work_thread.join() 


     self.p.stop() 

     self.status['text'] = "Files have been copyied".format(self.status) 

    def copyy2(self): 

     shutil.copytree(self.source_direcotry0, self.cam0) 
     shutil.copytree(self.source_direcotry1, self.cam1) 
     shutil.copytree(self.source_direcotry2, self.cam2) 
     shutil.copytree(self.source_direcotry3, self.cam3) 
     shutil.copytree(self.source_direcotry4, self.cam4) 
     shutil.copytree(self.source_direcotry5, self.cam5) 
     shutil.copytree(self.source_direcotry6, self.cam6) 
     shutil.copytree(self.source_direcotry7, self.cam7) 
     shutil.copytree(self.source_direcotry8, self.cam8) 
     shutil.copytree(self.source_direcotry9, self.cam9) 
     shutil.copytree(self.source_direcotry10, self.cam10) 
     shutil.copytree(self.source_direcotry11, self.cam11) 

    def deletee(self): 
     send2trash('/Volumes/CAM0/DCIM') 
     send2trash('/Volumes/CAM1/DCIM') 
     send2trash('/Volumes/CAM2/DCIM') 
     send2trash('/Volumes/CAM3/DCIM') 
     send2trash('/Volumes/CAM4/DCIM') 
     send2trash('/Volumes/CAM5/DCIM') 
     send2trash('/Volumes/CAM6/DCIM') 
     send2trash('/Volumes/CAM7/DCIM') 
     send2trash('/Volumes/CAM8/DCIM') 
     send2trash('/Volumes/CAM9/DCIM') 
     send2trash('/Volumes/CAM10/DCIM') 
     send2trash('/Volumes/CAM11/DCIM') 

     self.status['text'] = "Files have been moved to trash".format(self.status) 


    def client_exit(self): 
     exit() 

    def about_popup(self): 
     messagebox.showinfo("About", "This is software used to copy or delete files in bulk from the Absolute Zero VR camera") 


    #Creation of init_window 
    def init_window(self): 

     self.Source=StringVar() 
     self.Destination=StringVar() 


     # changing the title of our master widget  
     self.master.title("AZ Data Extractor") 

     # allowing the widget to take the full space of the root window 
     self.pack(fill=BOTH, expand=1) 

     #Creating the menu 
     self.menubar = Menu(self.master) 

     #Creating submenues 
     self.filemenu = Menu(self.menubar, tearoff=0) 
     self.filemenu.add_command(label="Exit", command=root.quit) 
     self.menubar.add_cascade(label="File", menu=self.filemenu) 

     self.helpmenu = Menu(self.menubar, tearoff=0) 
     self.helpmenu.add_command(label="About", command=self.about_popup) 
     self.menubar.add_cascade(label="Help", menu=self.helpmenu) 

     #Displaying the menu 
     root.config(menu=self.menubar) 

     #Creating the intro label 
     l_instruction = Label(self, justify=CENTER, compound=TOP, text="Choose the destination for the copied files \n and press 'Go!' to start copyting", bg="#E6E6E6") 
     l_instruction.grid(columnspan=2, ipady=10) 

     l_instruction = Label(self, justify=CENTER, compound=TOP, text="Press 'Delete' to move all files \n from the camera to the trash", bg="#E6E6E6") 
     l_instruction.grid(row=6, columnspan=2, ipady=10) 

     #Creating the button 
     MyDestination=Entry(self, textvariable=self.Destination,highlightbackground="#E6E6E6") 
     MyDestination.grid(row=2, columnspan=2, ipady=10) 
     uploadButton = Button(self, text="Choose destination folder",command=lambda:self.Destination.set(fdialog.askdirectory()),highlightbackground="#E6E6E6") 
     uploadButton.grid(row=3, columnspan=2, ipady=10) 
     goButton = Button(self, text="Go!",command=self.bar_init,highlightbackground="#E6E6E6") 
     goButton.grid(row=4, columnspan=2, ipady=10) 
     delButton = Button(self, text="Delete",command=self.deletee,highlightbackground="#E6E6E6") 
     delButton.grid(row=7, columnspan=2, ipady=10) 

     s = ttk.Style() 
     s.theme_use('alt') 
     s.configure("grey.Horizontal.TProgressbar", troughcolor='#E6E6E6', background='gray', bordercolor='#E6E6E6') 

     self.p = ttk.Progressbar(self, style="grey.Horizontal.TProgressbar", orient=HORIZONTAL, length=300, mode='indeterminate') 
     self.p.grid(row=5) 

     render = PhotoImage(file="az.gif") 
     img = Label(self, image=render, bg="#E6E6E6") 
     img.image = render 
     img.grid(row=10) 

     space = Label(self, bg="#E6E6E6") 
     space.grid(row=8) 
     space2 = Label(self, bg="#E6E6E6") 
     space2.grid(row=9) 
     space3 = Label(self, bg="#E6E6E6") 
     space3.grid(row=11) 


     #resizing configuration 
     self.grid_columnconfigure(0,weight=1) 
     self.grid_columnconfigure(1,weight=1) 
     self.grid_rowconfigure(0,weight=1) 
     self.grid_rowconfigure(1,weight=1) 
     self.grid_rowconfigure(2,weight=1) 
     self.grid_rowconfigure(3,weight=1) 
     self.grid_rowconfigure(4,weight=1) 
     self.grid_rowconfigure(5,weight=1) 
     self.grid_rowconfigure(6,weight=1) 
     self.grid_rowconfigure(7,weight=1) 
     self.grid_rowconfigure(8,weight=1) 
     self.grid_rowconfigure(9,weight=1) 
     self.grid_rowconfigure(10,weight=1) 
     self.grid_rowconfigure(11,weight=1) 


     #status Bar 
     self.status = Label(self.master, text="Waiting for process to start...", bd=1, relief=SUNKEN, anchor=W) 
     self.status.pack(side=BOTTOM, fill=X) 


# root window created. Here, that would be the only window, but you can later have windows within windows. 
root = Tk() 
root.resizable(width=False,height=False); 
#root.geometry("230x340") 



#creation of an instance 
app = Window(root) 

#mainloop 
root.mainloop() 
+0

我現在已經意識到,這種延遲並不總是相同的有時更大,有時它是相當小的。也許這不是由於代碼而是一些外部因素?但另一方面,在我引入線程之前,複製函數總是立即執行。 – Bart