Some background:
I have a class that inherits from tk.Label; basically, a Label widget that has some extra methods tuned to my taste.
I have two design modes for the label, and a function switching between them. Mode 1 is a simple look with black text; mode 2 is a look that has two empty blue frames inside the label, solely for design purposes (but are required).
The custom-widget (let's name it Cell) is bound to a function that changes the bg color (no matter which mode) of the Cell when clicked, and reverts when released.
Now, the situation:
Case I:- When Cell object is in "mode 1"
When the label is clicked and released, bg color changes respectively. Normal behaviour
Case II:- When Cell object is in "mode 2"
There are initially two frames in the frame.
When the label is clicked, bg color changes alright, but the frames suddenly disappear. The frames don't reappear, unless window is resized.
I doubted if the frames were sent behind of the Cell object (which seems absurd to me) and tried .lift()ing it. No success. Then I tried .update() and .update_idletasks() on the Cell object. No success again.
I want the frames to not disappear when I do .config(bg="new bg") and not need to resize the window just to make them reappear (don't know why this is needed)
Is this the way it is supposed to work - hiding the frames for some reason on configuring the label attributes? If so, what can be a way around it?
Minimal code attached below:
import tkinter as tk
def setMode1():
f1.place_forget()
f2.place_forget()
def setMode2():
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
on_click = lambda event: Cell.config(bg="#9999CC")
on_release = lambda event: Cell.config(bg="#CCCCFF")
window = tk.Tk()
window.wm_geometry("240x380")
Cell = tk.Label(window, text="TEXT", bg="#CCCCFF")
Cell.bind("<Button-1>", on_click)
Cell.bind("<ButtonRelease-1>", on_release)
f1 = tk.Frame(Cell, bg="#66AAFF")
f2 = tk.Frame(Cell, bg="#66AAFF")
Cell.place(width=240, height=200, y=25)
tk.Button(window, text="Mode 1", command=setMode1).place(width=100, height=40, x=70, y=250)
tk.Button(window, text="Mode 2", command=setMode2).place(width=100, height=40, x=70, y=315)
window.mainloop()
(I had posted the same question earlier but realised it was way too verbose. This is a shorter version) Any inputs to resolve the issue would be highly appreciated.
CodePudding user response:
The frames are just being pushed behind the background of the label. You can add some code like this to fix the issue:
import tkinter as tk
def setMode1():
global mode
f1.place_forget()
f2.place_forget()
mode = 1
def setMode2():
global mode
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
mode = 2
on_click = lambda event: Cell.config(bg="#9999CC")
def on_release(event):
Cell.config(bg="#CCCCFF")
if mode == 2:
f1.place_forget()
f2.place_forget()
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
mode = 0
window = tk.Tk()
window.wm_geometry("240x380")
Cell = tk.Label(window, text="TEXT", bg="#CCCCFF")
Cell.bind("<Button-1>", on_click)
Cell.bind("<ButtonRelease-1>", on_release)
f1 = tk.Frame(Cell, bg="#66AAFF")
f2 = tk.Frame(Cell, bg="#66AAFF")
Cell.place(width=240, height=200, y=25)
tk.Button(window, text="Mode 1", command=setMode1).place(width=100, height=40, x=70, y=250)
tk.Button(window, text="Mode 2", command=setMode2).place(width=100, height=40, x=70, y=315)
window.mainloop()
This just adds a variable mode that tells on_release how to treat the frames. It basically forces the program to add the frames when it needs to.
CodePudding user response:
Label is not designed for holding other widgets. Better use a frame to hold the label and the two frames instead:
import tkinter as tk
def setMode1():
f1.place_forget()
f2.place_forget()
def setMode2():
f1.place(relwidth=1, relheight=0.1)
f2.place(relwidth=1, relheight=0.1, rely=0.9)
on_click = lambda event: Cell.config(bg="#9999CC")
on_release = lambda event: Cell.config(bg="#CCCCFF")
window = tk.Tk()
window.wm_geometry("240x380")
# outer frame to hold the label and the two frames
container = tk.Frame(window)
container.place(width=240, height=200, y=25)
Cell = tk.Label(container, text="TEXT", bg="#CCCCFF")
Cell.place(relwidth=1, relheight=1)
Cell.bind("<Button-1>", on_click)
Cell.bind("<ButtonRelease-1>", on_release)
f1 = tk.Frame(container, bg="#66AAFF")
f2 = tk.Frame(container, bg="#66AAFF")
tk.Button(window, text="Mode 1", command=setMode1).place(width=100, height=40, x=70, y=250)
tk.Button(window, text="Mode 2", command=setMode2).place(width=100, height=40, x=70, y=315)
window.mainloop()
