Trouble with Tkinter labels - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: Trouble with Tkinter labels (/thread-40699.html) |
Trouble with Tkinter labels - Raysz - Sep-09-2023 So I am new at Tkinter So I'm trying to create what I thought was a simple program I made this program in a standard Python script I thought all I had to do was convert certain things over to Tkinter but I'm finding out that's not true This simple script downloads my programs from my archive to a Pacific folder and then install it, the download part works perfectly But when it comes time to install them I am using os.system when this is activated the labels will not display their contents it's almost like it bypasses the labels I have used time.sleep() just before os.system and that didn't solve my problem either if I remove os.system and replace it with print() both labels will work so I don't know what else to try I am opened up for suggestions # ---- download the program ---- down_inst = Label(root, text='Downloading ' + ck_folder + ' from archive', font=('Arial', 15)) down_inst.place(x=100, y=420) root.after(5000, down_inst.destroy) # 1000=1 second shutil.copyfile(dw_source_path + dw_file_name, td_dest_path + dw_file_name) # ---- installing program ---- down_inst = Label(root, text='And Installing ' + ck_folder, font=('Arial', 15)) down_inst.place(x=150, y=450) root.after(5000, down_inst.destroy) # 1000=1 second os.system(td_dest_path + dw_file_name + parameters) parameters = r' /S /norestart' RE: Trouble with Tkinter labels - menator01 - Sep-10-2023 Are you trying to get some kind of effect like this? import tkinter as tk from random import choice textlist = ['text', 'more text', 'how about this?', 'still more text', 'some text'] def destroy_label(root, label): label.destroy() root.after(3000, lambda: create_label(root, label)) def create_label(root, label): label = tk.Label(root, text=choice(textlist), font=(None, 25, 'normal')) label.pack(fill='x') root.after(3000, lambda: destroy_label(root, label)) root = tk.Tk() label = tk.Label(root,text='Some text', font=(None, 25, 'normal')) label.pack(fill='x') root.after(3000, lambda: destroy_label(root, label)) root.mainloop() RE: Trouble with Tkinter labels - Raysz - Sep-10-2023 (Sep-10-2023, 12:31 AM)menator01 Wrote: Are you trying to get some kind of effect like this? Thank you for replying Sorry if I haven't explain myself very well I am still considered a new programmer I can't give you the whole thing so maybe this will help Basically this script looks for a program on the computer it will ask you if you want to install it if it doesn't exist this script also contains a sub script this is the sub script below where I can add items to the list as you see below I am using ccleaner as an example import os # items in listbox my_listbox.insert(0, 'install ccleaner') my_listbox.insert(1, 'install empty for now') my_listbox.insert(2, 'install empty for now') my_listbox.insert(3, 'install empty for now') my_listbox.insert(4, '333install empty for now') def path_check_locations(): label = Label(root, text='looking for: ' + ck_folder, font=('Arial', 15)) label.place(x=150, y=420) root.after(5000, label.destroy) # 1000=1 second if os.path.isdir(os.path.join(ck_root, ck_folder)): label = Label(root, text='exists in root : ', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second elif os.path.isdir(os.path.join(ck_dir1, ck_folder)): label = Label(root, text='exists in Program Files', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second elif os.path.isdir(os.path.join(ck_dir2, ck_folder)): label = Label(root, text='exists in Program Files (x86)', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second else: label = Label(root, text=ck_folder + ' Doesnt exist', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second root.bell() if messagebox.askyesno(title='program installation', message='Do you want to install ' + ck_folder): # ---- exists or not ---- if not os.path.exists(td_dest_path): # ---- if not created ---- os.makedirs(td_dest_path) # ---- download the program ---- down_inst = Label(root, text='Downloading ' + ck_folder + ' from archive', font=('Arial', 15)) down_inst.place(x=100, y=420) root.after(5000, down_inst.destroy) # 1000=1 second shutil.copyfile(dw_source_path + dw_file_name, td_dest_path + dw_file_name) # ---- installing program ---- down_inst = Label(root, text='And Installing ' + ck_folder, font=('Arial', 15)) down_inst.place(x=150, y=450) root.after(5000, down_inst.destroy) # 1000=1 second print('Hi') os.system(td_dest_path + dw_file_name + parameters) else: label = Label(root, text="As you wish I won't install " + ck_folder, font=('Arial', 15)) label.place(x=100, y=450) root.after(5000, label.destroy) # 1000=1 second """ [global-variable-undefined] look in your Documentation about this this will help with variables so that this doesn't happen [global-variable-undefined] """ # ----[global-variable-undefined]---- ck_folder = 'Hi Ray' # the name here is unimportant dw_file_name = 'Hi Ray' # the name here is unimportant # ----path check locations---- ck_root = r'C:\\' ck_dir1 = r'\Program Files' ck_dir2 = r'\Program Files (x86)' # ----Download program, Where the programs are kept---- dw_source_path = r'\\source location' # ----installs the program---- parameters = r' /wait/S /norestart' # space after r' needs to be there to work correctly def sel_0(): global ck_folder # [global-variable-undefined] ck_folder = 'ccleaner' # name of folder to look for global dw_file_name dw_file_name = r'\ccsetup551.exe' # name of executable file path_check_locations() def sel_1(): # this label is towards the bottom of the window label = Label(root, text='looking for: ' + ck_folder, font=('Arial', 15)) label.place(x=150, y=420) root.after(5000, label.destroy) # 1000=1 second def sel_2(): # this label is towards the bottom of the window label = Label(root, text="Test is this 2", font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second print('Test is this 2') def sel_3(): # this label is towards the bottom of the window label = Label(root, text="Test is this 3", font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second print('Test is this 3') def sel_4(): # this label is towards the bottom of the window label = Label(root, text="Test is this 4", font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second print('Test is this 4') def select(): # this is linked to the Menu_Tkinter.py # this calls the functions from above selection = my_listbox.curselection() if selection == (0,): sel_0() elif selection == (1,): sel_1() elif selection == (2,): sel_2() elif selection == (3,): sel_3() elif selection == (4,): sel_4() RE: Trouble with Tkinter labels - deanhystad - Sep-10-2023 This does not draw the label. down_inst = Label(root, text='And Installing ' + ck_folder, font=('Arial', 15)) down_inst.place(x=150, y=450)This draws the label root.mainloop()You can see this if you run the program below. We force the window to update after making the first label, but the second label waits for mainloop() to update the root window. import tkinter as tk from time import sleep root = tk.Tk() tk.Label(root, text="How many labels", font=(None, 64)).pack() root.update() tk.Label(root, text="do you see?", font=(None, 64)).pack() sleep(5) root.mainloop()And before you start adding update() commands all over the place, stop and think about what you are using tkinter for. If you block mainloop() from running the window stops responding to user actions (button clicks, typing) and the window stops updating, even if you make request to change the windows appearance. Do you want your window to go dead while the program is busy. Your users will not be impressed. Are you blocking mainloop() from running? Is there something that takes a long time to run and this prevents your window from updating? If so, that code should be run in a separate thread. This is not the correct way to modify a label. down_inst = Label(root, text='Downloading ' + ck_folder + ' from archive', font=('Arial', 15)) down_inst.place(x=100, y=420) root.after(5000, down_inst.destroy) # 1000=1 second shutil.copyfile(dw_source_path + dw_file_name, td_dest_path + dw_file_name) # ---- installing program ---- down_inst = Label(root, text='And Installing ' + ck_folder, font=('Arial', 15)) down_inst.place(x=150, y=450)You should hardly ever use destroy(). Make the window and labels at the start of run. To display a different message, change the label text. The example below uses a tk.StringVar to change the label text. import tkinter as tk from time import sleep class Window(tk.Tk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.message = tk.StringVar() label = tk.Label(self, textvariable=self.message, width=60, font=(None, 32)) label.pack(padx=10, pady=10) def display_message(self, message_list, delay=10): if message_list: self.message.set(message_list[0]) self.after(delay * 1000, self.display_message, message_list[1:], delay) else: self.message.set("") window = Window() window.display_message( ( "Twas the night before Christmas, when all through the house", "Not a creature was stirring, not even a mouse", "The stockings were hung by the chimney with care", "In hopes that St. Nicholas soon would be there", ), delay=3, ) window.mainloop()You should not use place() to set the location of a widget. Use pack() or grid(). What if you have a user that selected a larger system font? Your labels will resize, but are they correctly spaced? Using pack() or grid() lets tkinter adjust the window to fit the contents. It also lets you easily make resizable windows. RE: Trouble with Tkinter labels - deanhystad - Sep-10-2023 You must really like typing. As far as I am concerned, this is duplicate code, and duplicate code should be avoided. if os.path.isdir(os.path.join(ck_root, ck_folder)): label = Label(root, text='exists in root : ', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second elif os.path.isdir(os.path.join(ck_dir1, ck_folder)): label = Label(root, text='exists in Program Files', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second elif os.path.isdir(os.path.join(ck_dir2, ck_folder)): label = Label(root, text='exists in Program Files (x86)', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second else: label = Label(root, text=ck_folder + ' Doesnt exist', font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 secondSame thing here. Nearly duplicate code. def sel_0(): global ck_folder # [global-variable-undefined] ck_folder = 'ccleaner' # name of folder to look for global dw_file_name dw_file_name = r'\ccsetup551.exe' # name of executable file path_check_locations() def sel_1(): # this label is towards the bottom of the window label = Label(root, text='looking for: ' + ck_folder, font=('Arial', 15)) label.place(x=150, y=420) root.after(5000, label.destroy) # 1000=1 second def sel_2(): # this label is towards the bottom of the window label = Label(root, text="Test is this 2", font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second print('Test is this 2') def sel_3(): # this label is towards the bottom of the window label = Label(root, text="Test is this 3", font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second print('Test is this 3') def sel_4(): # this label is towards the bottom of the window label = Label(root, text="Test is this 4", font=('Arial', 15)) label.place(x=150, y=450) root.after(5000, label.destroy) # 1000=1 second print('Test is this 4') def select(): # this is linked to the Menu_Tkinter.py # this calls the functions from above selection = my_listbox.curselection() if selection == (0,): sel_0() elif selection == (1,): sel_1() elif selection == (2,): sel_2() elif selection == (3,): sel_3() elif selection == (4,): sel_4()When I see a program where the same instructions appear over and over again, I see if I can separate the code that is the same each time from the code that is different. In this example, the methods that are performed when you select a program are the same for each program. The only thing that changes is the folder where the program files might reside. The code that executes the programs is likely very similar. Code that is the same, regardless of the selection, and code that is specific to each program. In the code below I put the program specific stuff, dictionaries and commands, in a dictionary. This lets me use the same code to install any program. import tkinter as tk from tkinter import ttk from pathlib import Path import shutil # Where I look for programs program_paths = { "root": Path("c:/"), "Program Files": Path("c:/Program Files"), "Program Files (x86)": Path("c:/Program Files (x86)"), } # Programs I can install programs = { "ccleaner": ["folder name", "print('Replace with command to install ccleaner')"], "dirtier": ["folder name", "print('Replace with command to install dirtier')"], } class Window(tk.Tk): def __init__(self): super().__init__() label = tk.Label(self, text="Select Program") self.program = tk.StringVar() selector = ttk.Combobox(self, textvariable=self.program, values=list(programs)) selector.bind("<<ComboboxSelected>>", self.select_program) self.message = tk.StringVar(self, "No program Selected") message = tk.Label(self, textvariable=self.message, width=60) self.button = tk.Button( self, text="Install Program", command=self.install_program, state=tk.DISABLED, ) label.grid(row=0, column=0, padx=10, pady=10, sticky="news") selector.grid(row=0, column=1, padx=(0, 10), pady=10, sticky="news") message.grid( row=1, column=0, columnspan=2, padx=10, pady=(0, 10), sticky="news" ) self.button.grid( row=2, column=0, columnspan=2, padx=10, pady=(0, 10), sticky="news" ) def set_message(self, message): self.message.set(message) self.update() def select_program(self, *_): program = self.program.get() for folder, path in program_paths.items(): if (path / folder).is_dir(): self.message.set(f"{program} found in {str(path)}.") self.button["state"] = tk.DISABLED else: self.message.set(f"{program} not found.") self.button["state"] = tk.NORMAL def install_program(self): program = self.program.get() folder, command = programs[program] # If command can take long time, can run this code in another thread. (Path(td_dest_path) / folder).mkdir(parents=True, exist_ok=True) self.set_message(f"Installing {program}") eval(command) # <- This executes the python command from the programs directory. self.set_message("") Window().mainloop()To add another program to my program, all I have to do is add an entry to the programs dictionary. RE: Trouble with Tkinter labels - Raysz - Sep-10-2023 (Sep-10-2023, 03:46 PM)deanhystad Wrote: This does not draw the label. Wow thank you very much most of these I got from YouTube I assume they knew what they were talking about but it just goes to show can't believe everything you see thanks a lot for looking at my program I will look at what you have and compare with what I've learned and make the necessary adjustments thanks again RE: Trouble with Tkinter labels - deanhystad - Sep-11-2023 Wading through the sea of crap that is python tutorials and videos to find the few that are good could be a full time job. It doesn't help that the same "lessons" are regurgitated by anyone who likes python and has a blog. Even content from trustworthy sources is often out-of-date or just barely scratches the surface. Trust nothing. Verifiy everything. Including this. Always use multiple sources. |