Tkinter Error, _tkinter.TclError, two progress bar windows show up _tkinter.TclError: invalid command name ".!toplevel3.!progressbar"

36 views Asked by At

Thanks for stopping by at my post; as amateur python writer, I'm writing a code to schedule a Copy & Paste process based on time previously defined by a user.

There should be 3 different times in the day where the copy & paste process should be executed. When I run the process independently it works just fine, however, when I try to run two or moew the error I'm having is that the Progress creates a secondary window causing the code fail trying to close two windows, the actual progress bar and the "parasite" progress bar.

When I run only one process only pop-up one single progress bar pop-up once and close without no issues.

However, when I run two process simultaneously, at the time schedule one executed opens two progress bar however when Tkinter try to close it the two bars it shows an error. please see below my code:

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
import shutil
from threading import Thread 
import os
from datetime import datetime
import schedule, time
from tkinter import simpledialog

class FileCopyGUI:
    def __init__(self, master):
        global time_str_one, time_str_two, time_str_three
        time_str_one="";time_str_two="";time_str_three=""
        self.password_unlock = "h"
        self.password_stop = "o"
        self.master = master
        self.master.title("Simple  - PreParser Tool v1.00")
        self.master.iconbitmap("simple.ico")
        self.master.resizable(False,False)

        def update_time():
            current_time = datetime.now().strftime("%I:%M:%S %p")
            current_date = datetime.now().strftime("%d %b, %Y")
            self.datetime_label = tk.Label(text=("Date & Time "), font=("Tahoma", 11))
            self.datetime_label.grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
            self.datetime_label = tk.Label(text=("" + current_date + ", " + current_time), font=("Tahoma", 11))
            self.datetime_label.grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)
            self.master.after(1000, update_time)  # Update every 1 second
        update_time()

        self.source_label = tk.Label(master, text="Source ", font=("Tahoma", 11), state=tk.DISABLED)
        self.source_label.grid(row=1, column=0, sticky=tk.W, padx=5, pady=5)
        self.source_entry = tk.Entry(master, width=50, font=("Tahoma", 11), state=tk.DISABLED)
        self.source_entry.grid(row=1, column=1,  sticky=tk.W, padx=5, pady=5)
        self.source_button = tk.Button(master, text=" Browse Folder ", font=("Tahoma", 11), command=self.browse_source, state=tk.DISABLED)
        self.source_button.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)

        self.destination_label = tk.Label(master, text="Destination ", font=("Tahoma", 11), state=tk.DISABLED)
        self.destination_label.grid(row=2, column=0, sticky=tk.W, padx=5, pady=5)
        self.destination_entry = tk.Entry(master, width=50, font=("Tahoma", 11), state=tk.DISABLED)
        self.destination_entry.grid(row=2, column=1, sticky=tk.W, padx=5, pady=5)
        self.destination_button = tk.Button(master, text=" Browse Folder ", font=("Tahoma", 11), command=self.browse_destination, state=tk.DISABLED)
        self.destination_button.grid(row=2, column=2,  sticky=tk.W, padx=5, pady=5)

        self.schedule_one = ttk.Label(master, text="Enter time schedule 1 ", font=("Tahoma", 11), state=tk.DISABLED)
        self.schedule_one.grid(row=3, column=0, sticky=tk.W, padx=5, pady=5)
        self.time_entry_one = tk.Entry(master, width=10, font=("Tahoma", 11), state=tk.DISABLED)
        self.time_entry_one.grid(row=3, column=1, sticky=tk.W, padx=5, pady=5)
        self.schedule_button_one = tk.Button(master, text="    Schedule    ", font=("Tahoma", 11), command=self.schedule_1, state=tk.DISABLED)
        self.schedule_button_one.grid(row=3, column=2, sticky=tk.W, padx=5, pady=5)

        self.schedule_two = ttk.Label(master, text="Enter time schedule 2 ", font=("Tahoma", 11), state=tk.DISABLED)
        self.schedule_two.grid(row=4, column=0, sticky=tk.W, padx=5, pady=5)
        self.time_entry_two = tk.Entry(master, width=10, font=("Tahoma", 11), state=tk.DISABLED)
        self.time_entry_two.grid(row=4, column=1, sticky=tk.W, padx=5, pady=5)
        self.schedule_button_two = tk.Button(master, text="    Schedule    ", font=("Tahoma", 11), command=self.schedule_2, state=tk.DISABLED)
        self.schedule_button_two.grid(row=4, column=2, sticky=tk.W, padx=5, pady=5)

        self.schedule_three = ttk.Label(master, text="Enter time schedule 3 ", font=("Tahoma", 11), state=tk.DISABLED)
        self.schedule_three.grid(row=5, column=0, sticky=tk.W, padx=5, pady=5)
        self.time_entry_three = tk.Entry(master, width=10, font=("Tahoma", 11), state=tk.DISABLED)
        self.time_entry_three.grid(row=5, column=1, sticky=tk.W, padx=5, pady=5)
        self.schedule_button_three = tk.Button(master, text="    Schedule    ", font=("Tahoma", 11), command=self.schedule_3, state=tk.DISABLED)
        self.schedule_button_three.grid(row=5, column=2, sticky=tk.W, padx=5, pady=5)

        self.unlock_button = tk.Button(master, text="    Locked...    ", command=self.check_password, font=("Tahoma", 11))
        self.unlock_button.grid(row=10, column=1, sticky=tk.W, padx=0, pady=5)
        self.run_button = tk.Button(master, text="       RUN      ", font=("Tahoma", 11), command=self.copy_files, state=tk.DISABLED)
        self.run_button.grid(row=10, column=1, sticky=tk.W, padx=160, pady=0)
        self.stop_button = tk.Button(master, text="       STOP     ", font=("Tahoma", 11), command=self.clear_gui, state=tk.DISABLED)
        self.stop_button.grid(row=10, column=1, sticky=tk.W, padx=315, pady=5)

        self.simple_label = tk.Label(master, text="Simple   ", font=("Tahoma", 8))
        self.simple_label.grid(row=11, column=0, sticky=tk.W, padx=0, pady=0)
        self.simple_label = tk.Label(master, text="Engineering Services ", font=("Tahoma", 8))
        self.simple_label.grid(row=12, column=0, sticky=tk.W, padx=0, pady=0)
        self.simple_label = tk.Label(master, text="  Simple ", font=("Tahoma", 8, "italic", "bold"), fg="blue" )
        self.simple_label.grid(row=13, column=0, sticky=tk.W, padx=0, pady=0)
        self.simple_label = tk.Label(master, text="www.s.com.mx ", font=("Tahoma", 8))
        self.simple_label.grid(row=14, column=0, sticky=tk.W, padx=0, pady=0)

    def check_password(self):
        entered_password = tk.simpledialog.askstring("Simple  - PreParser Tool v1.00", "Enter Password", show='*')
        if entered_password == self.password_unlock:
            messagebox.showinfo("Simple  - PreParser Tool v1.00", " Access Granted...! ")
            self.unlock_button = tk.Button(text="  Unlocked...    ", font=("Tahoma", 11))
            self.unlock_button.grid(row=10, column=1, sticky=tk.W, padx=0, pady=5)
            self.unlock_button.config(state=tk.DISABLED)
            self.source_label.config(state=tk.NORMAL)
            self.source_entry.config(state=tk.NORMAL)
            self.source_button.config(state=tk.NORMAL)
            self.destination_label.config(state=tk.NORMAL)
            self.destination_entry.config(state=tk.NORMAL)
            self.destination_button.config(state=tk.NORMAL)
        else:
            messagebox.showerror("Simple  - PreParser Tool v1.00", "Incorrect Password...! Please try again")
            return

    def browse_source(self):
        global source_folder
        source_folder = filedialog.askdirectory()
        if source_folder:
            self.source_entry.delete(0, tk.END)
            self.source_entry.insert(0, source_folder)

    def browse_destination(self):
        global destination_folder
        destination_folder = filedialog.askdirectory()
        if destination_folder:
            self.destination_entry.delete(0, tk.END)
            self.destination_entry.insert(0, destination_folder)

        if (destination_folder) != "" and (source_folder) != "":
            self.schedule_one.config(state=tk.NORMAL)
            self.time_entry_one.config(state=tk.NORMAL)
            self.schedule_button_one.config(state=tk.NORMAL)
            self.schedule_two.config(state=tk.NORMAL)
            self.time_entry_two.config(state=tk.NORMAL)
            self.schedule_button_two.config(state=tk.NORMAL)
            self.schedule_three.config(state=tk.NORMAL)
            self.time_entry_three.config(state=tk.NORMAL)
            self.schedule_button_three.config(state=tk.NORMAL)

    def schedule_1(self):
        global time_str_one, time_str_two, time_str_three
        time_str_one = self.time_entry_one.get()
        import re
        if re.match(r'^([01]?[0-9]|2[0-3]):[0-5][0-9]$', time_str_one):
            tk.messagebox.showinfo("Simple  - PreParser Tool v1.00", "Task has been properly scheduled to be executed")
            self.schedule_one.config(state=tk.DISABLED)
            self.time_entry_one.config(state=tk.DISABLED)
            self.schedule_button_one.config(state=tk.DISABLED)
            self.run_button.config(state=tk.NORMAL)
            self.stop_button.config(state=tk.NORMAL)
        else:
            tk.messagebox.showerror("Simple  - PreParser Tool v1.00", "Invalid time format. Please enter time in 12-hour HH:MM AM/PM format.")
            return

    def schedule_2(self):
        global time_str_one, time_str_two, time_str_three
        time_str_two = self.time_entry_two.get()
        import re
        if re.match(r'^([01]?[0-9]|2[0-3]):[0-5][0-9]$', time_str_two):
            tk.messagebox.showinfo("Simple  - PreParser Tool v1.00", "Task has been properly scheduled to be executed")
            self.schedule_two.config(state=tk.DISABLED)
            self.time_entry_two.config(state=tk.DISABLED)
            self.schedule_button_two.config(state=tk.DISABLED)
            self.run_button.config(state=tk.NORMAL)
            self.stop_button.config(state=tk.NORMAL)
        else:
            tk.messagebox.showerror("Simple  - PreParser Tool v1.00", "Invalid time format. Please enter time in 12-hour HH:MM AM/PM format.")
            return

    def schedule_3(self):
        global time_str_one, time_str_two, time_str_three
        time_str_three = self.time_entry_three.get()
        import re
        if re.match(r'^([01]?[0-9]|2[0-3]):[0-5][0-9]$', time_str_three):
            tk.messagebox.showinfo("Validation", "Task has been properly scheduled to be executed")
            self.schedule_three.config(state=tk.DISABLED)
            self.time_entry_three.config(state=tk.DISABLED)
            self.schedule_button_three.config(state=tk.DISABLED)
            self.run_button.config(state=tk.NORMAL)
            self.stop_button.config(state=tk.NORMAL)
        else:
            tk.messagebox.showerror("Simple  - PreParser Tool v1.00", "Invalid time format. Please enter time in 12-hour HH:MM AM/PM format.")
            return 
        
    def copy_files(self):
        if time_str_one:
            if time_str_two == "" or time_str_three=="":
                self.schedule_two.config(state=tk.DISABLED)
                self.time_entry_two.config(state=tk.DISABLED)
                self.schedule_button_two.config(state=tk.DISABLED)
                self.schedule_three.config(state=tk.DISABLED)
                self.time_entry_three.config(state=tk.DISABLED)
                self.schedule_button_three.config(state=tk.DISABLED)
            self.source_label.config(state=tk.DISABLED)
            self.source_entry.config(state=tk.DISABLED)
            self.source_button.config(state=tk.DISABLED)
            self.destination_label.config(state=tk.DISABLED)
            self.destination_entry.config(state=tk.DISABLED)
            self.destination_button.config(state=tk.DISABLED)
            self.run_button.config(state=tk.DISABLED)
            ##self.master.iconify()
            def copy_one():
                source = self.source_entry.get()
                destination = self.destination_entry.get()
                if not os.path.exists(source):
                    messagebox.showerror("PreParser Tool v1.00", "Source directory does not exist.")
                    return
                if not os.path.exists(destination):
                    messagebox.showerror("PreParser Tool v1.00", "Destination directory does not exist.")
                    return
                self.progress_window_one = tk.Toplevel(self.master)
                self.progress_window_one.iconbitmap("simple.ico")
                self.progress_window_one.title("Copying information per schedule 1...")
                self.progress_one = ttk.Progressbar(self.progress_window_one, orient="horizontal", length=600, mode="determinate")
                self.progress_one.grid(row=0, column=0, padx=5, pady=5)
                total_files = sum(len(files) for _, _, files in os.walk(source))
                copied_files = 0
                for root, dirs, files in os.walk(source):
                    for file in files:
                        source_file = os.path.join(root, file)
                        destination_file = os.path.join(destination, os.path.relpath(source_file, source))
                        os.makedirs(os.path.dirname(destination_file), exist_ok=True)
                        shutil.copy2(source_file, destination_file)
                        copied_files += 1
                        progress_percent_one = int((copied_files / total_files) * 100)
                        self.progress_one["value"] = progress_percent_one
                        self.progress_window_one.update()
                self.progress_window_one.destroy()
            def cycle_one():
                schedule.every().day.at(time_str_one).do(copy_one)
                while True:
                    print("cycle 1")
                    schedule.run_pending()
                    time.sleep(1)
            Thread(target=cycle_one).start()

        if time_str_two:
            if time_str_one == "" or time_str_three=="":
                self.schedule_one.config(state=tk.DISABLED)
                self.time_entry_one.config(state=tk.DISABLED)
                self.schedule_button_one.config(state=tk.DISABLED)
                self.schedule_three.config(state=tk.DISABLED)
                self.time_entry_three.config(state=tk.DISABLED)
                self.schedule_button_three.config(state=tk.DISABLED)
            self.source_label.config(state=tk.DISABLED)
            self.source_entry.config(state=tk.DISABLED)
            self.source_button.config(state=tk.DISABLED)
            self.destination_label.config(state=tk.DISABLED)
            self.destination_entry.config(state=tk.DISABLED)
            self.destination_button.config(state=tk.DISABLED)
            self.run_button.config(state=tk.DISABLED)
            ##self.master.iconify()
            def copy_two():
                source = self.source_entry.get()
                destination = self.destination_entry.get()
                if not os.path.exists(source):
                    messagebox.showerror("Simple  - PreParser Tool v1.00", "Source directory does not exist.")
                    return
                if not os.path.exists(destination):
                    messagebox.showerror("Simple  - PreParser Tool v1.00", "Destination directory does not exist.")
                    return
                self.progress_window_two = tk.Toplevel(self.master)
                self.progress_window_two.iconbitmap("simple.ico")
                self.progress_window_two.title("Copying information per schedule 2...")
                self.progress_two = ttk.Progressbar(self.progress_window_two, orient="horizontal", length=600, mode="determinate")
                self.progress_two.grid(row=0, column=0, padx=5, pady=5)
                total_files = sum(len(files) for _, _, files in os.walk(source))
                copied_files = 0
                for root, dirs, files in os.walk(source):
                    for file in files:
                        source_file = os.path.join(root, file)
                        destination_file = os.path.join(destination, os.path.relpath(source_file, source))
                        os.makedirs(os.path.dirname(destination_file), exist_ok=True)
                        shutil.copy2(source_file, destination_file)
                        copied_files += 1
                        progress_percent_two = int((copied_files / total_files) * 100)
                        self.progress_two["value"] = progress_percent_two
                        self.progress_window_two.update()
                self.progress_window_two.destroy()
            def cycle_two():
                schedule.every().day.at(time_str_two).do(copy_two)
                while True:
                    print("cycle 2")
                    schedule.run_pending()
                    time.sleep(1)
            Thread(target=cycle_two).start()

        if time_str_three:
            if time_str_one == "" or time_str_two=="":
                self.schedule_one.config(state=tk.DISABLED)
                self.time_entry_one.config(state=tk.DISABLED)
                self.schedule_button_one.config(state=tk.DISABLED)
                self.schedule_two.config(state=tk.DISABLED)
                self.time_entry_two.config(state=tk.DISABLED)
                self.schedule_button_two.config(state=tk.DISABLED)
            self.source_label.config(state=tk.DISABLED)
            self.source_entry.config(state=tk.DISABLED)
            self.source_button.config(state=tk.DISABLED)
            self.destination_label.config(state=tk.DISABLED)
            self.destination_entry.config(state=tk.DISABLED)
            self.destination_button.config(state=tk.DISABLED)
            self.run_button.config(state=tk.DISABLED)
            ##self.master.iconify()
            source = self.source_entry.get()
            destination = self.destination_entry.get()
            if not os.path.exists(source):
                messagebox.showerror("Simple  - PreParser Tool v1.00", "Source directory does not exist.")
                return
            if not os.path.exists(destination):
                messagebox.showerror("Simple  - PreParser Tool v1.00", "Destination directory does not exist.")
                return
            def copy_three():
                self.progress_window_three = tk.Toplevel(self.master)
                self.progress_window_three.iconbitmap("simple.ico")
                self.progress_window_three.title("Copying information per schedule 3...")
                self.progress_three = ttk.Progressbar(self.progress_window_three, orient="horizontal", length=600, mode="determinate")
                self.progress_three.grid(row=0, column=0, padx=5, pady=5)
                total_files = sum(len(files) for _, _, files in os.walk(source))
                copied_files = 0
                for root, dirs, files in os.walk(source):
                    for file in files:
                        source_file = os.path.join(root, file)
                        destination_file = os.path.join(destination, os.path.relpath(source_file, source))
                        os.makedirs(os.path.dirname(destination_file), exist_ok=True)
                        shutil.copy2(source_file, destination_file)
                        copied_files += 1
                        progress_percent_three = int((copied_files / total_files) * 100)
                        self.progress_three["value"] = progress_percent_three
                        self.progress_window_three.update()
                self.progress_window_three.destroy()
            def cycle_three():
                schedule.every().day.at(time_str_three).do(copy_three)
                while True:
                    print("cycle 3")
                    schedule.run_pending()
                    time.sleep(1)
            Thread(target=cycle_three).start()

    def clear_gui(self):
        entered_password = tk.simpledialog.askstring("Simple  - PreParser Tool v1.00", "Enter Password", show='*')
        if entered_password == self.password_stop:
            exit.set()
            self.source_entry.delete(0, tk.END)
            self.destination_entry.delete(0, tk.END)
        else:
            messagebox.showerror("Error", "Incorrect password!")
            return

def main():
    root = tk.Tk()
    app = FileCopyGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()
    
0

There are 0 answers