pass a variable between tkinter and toplevel windows - 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: pass a variable between tkinter and toplevel windows (/thread-40828.html) Pages:
1
2
|
pass a variable between tkinter and toplevel windows - janeik - Oct-02-2023 hello. I have 2 windows: a)window = tkinter.Tk(), a mapview and an Entry to write a filepath b)top=Toplevel() and a label to view an image I need to pass a dynamic variable (full filepath.i.e.: "d:/bilde/Rød.png" from window a to a PhotoImage function in window b. At present time, without success. Plan is to make an event (sv), view an image on label,in window b (exactly below an tkintermap in window a). It works ok as long as I hardcode the filepath in window b. My doubt is, does the event (sv) trigger the PhotoImage function after I manually write in filepath into an tkinter Entry in window a? (I might write/read a file to pass variable between windows, but that would be a none alternative and slow process). Below is some copies of code in each window. var1 in window a, shows correct path (entered from keyboard) No image is shown from window b. No errors detected. SOME CODE IN WINDOW A: import tkinter from Scripts import dati from Scripts import rutiner from tkinter.ttk import * import tkintermapview import customtkinter from tkinter import Canvas from tkinter import * from datetime import datetime from pynput.mouse import Button, Controller import tkinter as tk from PIL import ImageTk, Image import cv2 #---------------------GLOBAL VARIABLES------------------------- mouse = Controller() zoom=1 db = "D:/Python311/Scripts/markers.db" today = datetime.today( ).strftime("%d-%m-%Y-%H-%M-%S") verdi=0 stinavn1="" stinavn2="" stinavn3="" stinavn4="" textentered1="" var1="" root_tk = tkinter.Tk() window = root_tk window.geometry("1920x1200+0+0") window.minsize(1920, 1200) window.resizable(False, False) window.overrideredirect(True) window.attributes('-topmost',True). . def callback(sv): textentered1= str(sv.get()) var1 =textentered1 if "htt" in var1:stitype="web" elif ".png" in var1:stitype= "fil" elif ".mp4" in var1:stitype = "vid" elif ".docx" in var1:stiltype = "word" print(var1) sv = StringVar() sv.trace("w", lambda name, index, mode, sv=sv: callback(sv)) sti1 = customtkinter.CTkEntry(window, textvariable=sv, width=360, font=("Ariel",14,"bold"), placeholder_text="Sti til bilde 1 som skal behandles.(d:/bilde/abc.png)", justify=("left")) sti1.place(x=12,y=1010). . TOPLEVEL WINDOW: top = Toplevel() top.geometry("1000x1000") top.resizable(False, False) top.overrideredirect(True) histimg=PhotoImage(file="d:/bilde/Rød.png") (a png image with red circle) label=Label(top,image=histimg) label.place(x=0,y=0) window.mainloop() RE: pass a variable between tkinter and toplevel windows - deanhystad - Oct-02-2023 You cannot pass variables to functions in python. Python variables are only names that can be used to reference objects. When you use a variable name as an argument to a python function, you are passing the object referenced by the variable. Please do not write multiple statements on one line. It looks really odd. def callback(sv): textentered1= str(sv.get()) #<- This is a local variable, and why are you calling str()? var1 =textentered1 if "htt" in var1: stitype="web" # <- This is a local variable elif ".png" in var1: stitype= "fil" elif ".mp4" in var1: stitype = "vid" elif ".docx" in var1: stiltype = "word"A problem with this function is textentered1 is a local variable, not the global variable declared here: #---------------------GLOBAL VARIABLES------------------------- mouse = Controller() zoom=1 db = "D:/Python311/Scripts/markers.db" today = datetime.today( ).strftime("%d-%m-%Y-%H-%M-%S") verdi=0 stinavn1="" stinavn2="" stinavn3="" stinavn4="" textentered1="" var1=""You can fix this by adding "global textentered1, stiltype" at the top of the callback() function. "global" tells python to look for the variable name in the global scope instead of creating a local variable. I don't like using global variables, and the recommendation is to avoid using their use. Instead of having callback() set a global variable, it should perform some the actions that use the value in sv. Somewhere you must have some code that uses textentered1 and stiltype. That code should be in callback(), or should be called by callback(). I think that is what you refer to here: Quote:My doubt is, does the event (sv) trigger the PhotoImage function after I manually write in filepath into an tkinter Entry in window a?I think this is exactly what you should do. callback() should be bound to the control used to enter the filename. When you enter the filename, callback() should directly call the PhotoImage function and update the window. RE: pass a variable between tkinter and toplevel windows - Larz60+ - Oct-02-2023 A method that works well to send messages between queues is explained in this thread RE: pass a variable between tkinter and toplevel windows - deanhystad - Oct-02-2023 (Oct-02-2023, 08:55 AM)Larz60+ Wrote: A method that works well to send messages between queues is explained in this threadIs this a response to a different post? I don't see any mention of thread use. The "multiple windows" referenced in the post are all in the main thread. RE: pass a variable between tkinter and toplevel windows - Larz60+ - Oct-02-2023 deanhystad Wrote:Is this a response to a different post? I don't see any mention of thread use in the OP.Perhaps so. Just woke up. RE: pass a variable between tkinter and toplevel windows - janeik - Oct-03-2023 Thanks for input. I found a solution and will post it soon. RE: pass a variable between tkinter and toplevel windows - janeik - Oct-03-2023 (Oct-03-2023, 02:45 AM)janeik Wrote: Thanks for input. I found a solution and will post it soon. Used the callback and global variable var1,containing a filepath for an image to be shown on a label in top level window. MAIN WINDOW, ALLWAYS ON TOP root_tk = tkinter.Tk() window = root_tk window.geometry("1920x1200+0+0") window.minsize(1920, 1200) window.resizable(False, False) window.overrideredirect(True) window.attributes('-topmost',True)TOP LEVEL WINDOW (ALLOCATED BELOW MAINWINDOW def callback(sv): global var1 var1 = (sv.get()) sv = StringVar() sv.trace("w", lambda name, index, mode, sv=sv: callback(sv)) # sti1 = customtkinter.CTkEntry(window, textvariable=sv) sti1 = customtkinter.CTkEntry(window, textvariable=sv, width=360, font=("Ariel",14,"bold"), placeholder_text="Sti til bilde 1 som skal behandles.(d:/bilde/abc.png)", justify=("left")) sti1.place(x=12,y=1010) #------------------------create top level window and a label imglbl to hold image------------------------- top = Toplevel() top.geometry("1000x1000") top.resizable(False, False) top.overrideredirect(True) #------------------------function view image from path given in var1------------ def loadimg(): global var1 var1.strip() photo = PhotoImage(file=var1) image_label = Label(top,image=photo) image_label.photo = photo image_label.place(x=0,y=0) #----------button, at main window, execute loadimg() function button = tk.Button(window, text="Submit",command = loadimg) button.place(x=45,y=1140) RE: pass a variable between tkinter and toplevel windows - deanhystad - Oct-03-2023 I would do it like this: import tkinter as tk import customtkinter as ctk class OverlayWindow(tk.Toplevel): def __init__(self, overlay_file): self.overlay_file = overlay_file super().__init__() self.geometry("1000x1000") self.resizable(False, False) self.overrideredirect(True) tk.Button(self, text="Submit", command=self.loading).place(x=45,y=1140) def loadimg(self): """Set overlay image""" photo = tk.PhotoImage(file=self.overlay_file.get().strip()) image_label = tk.Label(self, image=photo) image_label.photo = photo image_label.place(x=0, y=0) class MainWindow(tk.Tk): def __init__(self): super().__init__() self.geometry("1920x1200+0+0") self.minsize(1920, 1200) self.resizable(False, False) self.overrideredirect(True) self.attributes('-topmost',True) self.overlay_file = tk.StringVar() ctk.CTkEntry( self, textvariable=self.overlay_file, width=360, font=("Ariel", 14, "bold"), placeholder_text="Sti til bilde 1 som skal behandles.(d:/bilde/abc.png)", justify=("left")).place(x=12,y=1010) window = MainWindow() top = OverlayWindow(window.overlay_file)If there are several values that top needs to get from window, I pass window to top, and use that to reference the values. class OverlayWindow(tk.Toplevel): def __init__(self, main_window): self.main_window = main_window super().__init__() self.geometry("1000x1000") self.resizable(False, False) self.overrideredirect(True) tk.Button(self, text="Submit", command=self.loading).place(x=45,y=1140) def loadimg(self): """Set overlay image""" photo = tk.PhotoImage(file=self.main_window.overlay.get().strip()) image_label = tk.Label(self, image=photo) image_label.photo = photo image_label.place(x=0, y=0)Another approach is to make a data model that is used by both windows. Think of it as a blackboard that both windows can read and write. import tkinter as tk import customtkinter as ctk class ApplicationData(): """I have all data shared between the main and overlay window.""" def __init__(self): self.overlay_file = tk.StringVar() # additional shared vaiables go here class OverlayWindow(tk.Toplevel): def __init__(self, data): self.data = data super().__init__() self.geometry("1000x1000") self.resizable(False, False) self.overrideredirect(True) tk.Button(self, text="Submit", command=self.loading).place(x=45,y=1140) def loadimg(self): """Set overlay image""" photo = tk.PhotoImage(file=self.data.overlay_file.get().strip()) image_label = tk.Label(self, image=photo) image_label.photo = photo image_label.place(x=0, y=0) class MainWindow(tk.Tk): def __init__(self, data): super().__init__() self.geometry("1920x1200+0+0") self.minsize(1920, 1200) self.resizable(False, False) self.overrideredirect(True) self.attributes('-topmost',True) ctk.CTkEntry( self, textvariable=self.data.overlay_file, width=360, font=("Ariel", 14, "bold"), placeholder_text="Sti til bilde 1 som skal behandles.(d:/bilde/abc.png)", justify=("left")).place(x=12,y=1010) data = ApplicationData() window = MainWindow(data) top = OverlayWindow(data)You should start studying Python classes. There is a reason that tkinter and customtkinter use classes. It is hard to write good looking GUI code without them. RE: pass a variable between tkinter and toplevel windows - janeik - Oct-05-2023 (Oct-03-2023, 01:48 PM)deanhystad Wrote: I would do it like this:Thanks for thee advices. I will probably change to oop affter Im finished without oop :) RE: pass a variable between tkinter and toplevel windows - janeik - Oct-05-2023 After doing following, using variations in transparency between main window hosting a fixed tkinger mapview and a historical map imagefile, seemes to work as expected. SETTING TOPMOST TO FALSE IN MAIN WINDOW window.attributes('-topmost',False) SETTING TOPMOST TO TRUE IN TOP LEVEL WINDOW top.attributes('-topmost',TRUE) ASSIGNING TRANSPARENCY ATTRIBUTE TO TOP LEVEL WINDOW FROM EVENTFUNCTION LOCATED IN MAIN WINDOW def slider1_event(value): top.attributes("-alpha",slider1.get()) slide1val.configure(text=str(round(value,2)))Activated slider with value initial set to 0.0 (no transparency. Removed 4 duplicate lines. |