Reputation: 329
Quick summary: The green button is supposed to change when an image is selected, but it doesn't:
I have a Tkinter window-A
with a button that when pressed will use a separate Python file to create a new window-B
. Window-B
has two buttons: new screen-snip or select image from folder. The method used for this is supposed to then change self.image_selected
so that it can be used to update the button in window-A
to have this new image.
I've tried both lines of code below, and neither are working. I'm not getting any errors either:
self.button.configure(image = img.image_selected) # first try
self.button['image'] = img.image_selected # second try
Here is my code (simplified for clarity):
import tkinter as tk
import get_image_or_snip
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height = 5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height = 5, text = "Select Image",
font = self.fontA, command = self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
self.newWindow = tk.Toplevel(self.master)
img = get_image_or_snip.AcquireImage(self.newWindow)
self.button.configure(image = img.image_selected)
#self.button['image'] = img.image_selected
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
Here is the aforementioned get_image_or_snip.py
code:
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk, Image
import snipping_tool
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command =lambda: self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command=lambda: self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
self.master.mainloop()
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename()
load_img = Image.open(ret)
self.image_selected = ImageTk.PhotoImage(load_img)
if method == 2:
ret = snipping_tool.get_snip()
self.image_selected = ret
def main():
root = tk.Tk()
AcquireImage(root)
root.mainloop()
if __name__ == '__main__':
main()
Upvotes: 2
Views: 96
Reputation: 142641
If you add print()
before and after get_image_or_snip.AcquireImage(self.newWindow)
in changeImage()
then you should see only first text because you run second mainloop()
and it never ends this loop and never go back to changeImage()
and never runs self.button.configure(image=img.image_selected)
You should use only one mainloop()
and eventually use
root.wait_window(self.newWindow)
to wait until you close second window and then it will run self.button.configure(image=img.image_selected)
But there are other problems.
It removes image from memory memory when second windows is destroyed so you have to assign it to variable in first window.
Button use height in chars when you sent text but when you assign image then it use height in pixels and you have to change it from 5
to image.height()`
All code in one file
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file=ret)
self.master.destroy()
elif method == 2:
self.image_selected = snipping_tool.get_snip()
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height=5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
font=self.fontA, command=self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
print('open second window')
self.newWindow = tk.Toplevel(self.master)
img = AcquireImage(self.newWindow)
self.master.wait_window(self.newWindow)
print('close second window')
if img.image_selected: # check if image was selected
self.image = img.image_selected
self.button.configure(image=self.image, height=self.image.height())
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
BTW: If you want to change image without closing second window then you should send first window (or button from first window) as argument to second window and change image in show_dialogs()
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk
class AcquireImage:
def __init__(self, master, first_window):
self.master = master
self.first_window = first_window
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file=ret)
self.first_window.image = self.image_selected
self.first_window.button.configure(image=self.first_window.image, height=self.first_window.image.height())
elif method == 2:
self.image_selected = snipping_tool.get_snip()
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height=5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
font=self.fontA, command=self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
self.newWindow = tk.Toplevel(self.master)
img = AcquireImage(self.newWindow, self) # first window as `self` but you can send `self.button`
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
EDIT: Doc about creating Dialog Windows
Upvotes: 2