Widgets disappear when main window moved off screen - python

I have a tkinter window that I have given a background picture by creating a Label widget with a PhotoImage instance (referencing the image instance through Label attributing).
However when I run the script and move the main window below the start menu (am using Windows 10) or past the sides of the screens for even one moment, all the widgets packed onto the Label (w/ background pic) completely disappear.
They only come back (somewhat) upon hovering over them with the mouse it seems. Also the background picture remains and continues to fill the screen. Could it be that the background picture Label is being "lifted" and makes it seem like the widgets are disappearing? If so, how can I prevent this from happening?
The fix that I have found for now is to not use a Label with a PhotoImage as the parent "frame", but instead use a typical Frame widget with only a background color, but this is not ideal.
import tkinter as tk
root = tk.Tk()
root.geometry('600x350+600+300')
root.resizable(width=False, height=False)
boxBg = '#666'
frameBg = '#fff'
#problem method
backgroundImg = tk.PhotoImage(file='program_media/background.png')
bgFrame = tk.Label(root, image=backgroundImg)
bgFrame.image = backgroundImg
#less than ideal solution so far
#bgFrame = tk.Frame(root, bg='#fff')
bgFrame.pack(expand=1, fill=tk.BOTH)
mainFrame = tk.Frame(bgFrame)
mainFrame.pack(side=tk.TOP)
title = tk.Label(mainFrame, text='Test String')
title.pack(side=tk.TOP)
#widget creation code packed within mainFrame
#...
#... All these widgets (including mainFrame above) are disappearing
#...
#end of widget creation code
root.mainloop()
See what I mean in this screenshot of BEFORE and AFTER moving the main window below the start menu.

Related

Tkinter Transparent Background macOS

I've been messing around with different code snippets and combinations for a while now, trying to make it so my .gif file would have a transparent background. I've been successful in making the actual background transparent, but I find that my .gif goes transparent with it:
import tkinter as tk
root = tk.Tk()
root.overrideredirect(1)
root.wm_attributes("-topmost", True)
root.wm_attributes("-transparent", True)
root.config(bg='systemTransparent')
root.geometry("+300+300")
root.image = tk.PhotoImage(file="sample.gif")
label = tk.Label(root, image=root.image)
label.config(bg='systemTransparent')
label.pack()
root.mainloop()
I have found that whenever I use both root.config(bg='systemTransparent') and label.config(bg='systemTransparent'), the entire window and gif go transparent, but when I use just one or neither, I am left with a light-gray background.

Creating a new window in tkinter that has the same widgets from the root window

I am wanting to create a tkinter window where when I click a button widget it opens a new window, showing all the widgets, exactly the same, from the root/original window. Essentially creating a second instance of the root window, where the application can have multiple users, using the same GUI, in different windows.
Any help is appreciated.
An example of one of my widgets:
summary_output = Text(
master=window,
height=8,
width=78,
bg="gray95",
borderwidth=2,
relief="groove",
font=("Arial", 12))
My window layout
window = Tk()
window.title("Data Viewer")
window.geometry("750x950")
window.configure(bg='white')
window.iconphoto(False, tk.PhotoImage(file='icon.png'))
I have this but cant seem to place the widgets from the root window:
def new_window():
newWindow = Toplevel(window)
newWindow.geometry("750x950")
newWindow.configure(bg='white')
newWindow.iconphoto(False, tk.PhotoImage(file='icon.png'))
upload_button.place(x=20, y=560)
mainloop()
Is their anyway to change the master to be any window?
Edit:
from tkinter import *
class StaticFrame(Frame):
def __init__(self,master,*args,**kwargs):
Frame.__init__(self,master,*args,**kwargs)
# All your widgets
Label(self,text='This is a reusable frame',font=(0,17)).place(x=0, y=0)
Button(self,text='Click me for nothing').pack()
Label(self,text='End of page').pack()
upload_button = Button(
self,
text="Edit Data",
fg="DodgerBlue4",
font=("Graph Type", 15),
height=1, width=12,
borderwidth=2,
relief="groove")
upload_button.place(x=20, y=50)
root = Tk() # First window
top = Toplevel(root) # Second window
root.geometry("750x968")
StaticFrame(root).pack() # Put the frame on the first window
StaticFrame(top).pack() # Put the frame on the second window
root.mainloop()
Result:
The concept used here is simple, create a "custom frame" that we will put onto these new windows, so that it will create the exact same frame, and widgets within it, inside different windows.
from tkinter import *
class StaticFrame(Frame):
def __init__(self,master,*args,**kwargs):
Frame.__init__(self,master,*args,**kwargs)
# All your widgets
Label(self,text='This is a reusable frame',font=(0,17)).pack()
Button(self,text='Click me for nothing').pack()
Label(self,text='End of page').pack()
root = Tk() # First window
top = Toplevel(root) # Second window
StaticFrame(root).pack() # Put the frame on the first window
StaticFrame(top).pack() # Put the frame on the second window
root.mainloop()
Very simple to code and has been explained with comments, if you do not know what classes and inheritance is then first do go through those. There are variety of other methods that come onto mind when I read this question, like even having an option database and storing the widgets in a list and recreating it based on its order, but this seems to be the easiest in a scratch.

Python's Tkinter Entry not appearing on window

I am trying to make a window that would take an input through an entry and that would be either a web address or ip address and i would use a loop to update the text of a label to show the current ping every second. But I'm stuck at the very beginning because my entry would not appear on my window. Here is my code:
import tkinter as tk
from tkinter import *
window = tk.Tk()
window.title("Server Status")
window.geometry('400x600')
window.resizable(0,0)
canvas = tk.Canvas(window,height=600,width=1000,bg='#263D42')
canvas.pack()
txtf=tk.Entry(window, width=10)
txtf.pack()
window.mainloop()
Where am I going wrong? I have tried it with several changes but still cant get it to appear there. Any help would be appreciated.
Thanks.
Your entry is below the canvas, but because (1) your window geometry specifies a smaller size than that requested for the canvas, and (2) you set it to be non resizable, you can never access it.
Choose how to resolve this conflict; the example below sets the size of the canvas, and lets the window resize to enclose all its widgets.
import tkinter as tk
window = tk.Tk()
window.title("Server Status")
canvas = tk.Canvas(window, height=600, width=1000, bg='#263D42')
canvas.pack()
txtf = tk.Entry(window, width=10)
txtf.pack()
window.mainloop()

How do I change the size of a tkinter canvas through a new window?

So I have one Tkinter screen that has a canvas. I want to change the size of the canvas by creating a new window that has entry widgets. So I created a new screen and added 2 entry widgets. I want to get the value from those widgets and based on that...it should change the size of the canvas. I tried to do this for an hour, but no luck. Please assist me.
Here is my code
from tkinter import *
# create root window
root = Tk()
# Create Canvas
canvas = Canvas(root, width=50, height=50)
# Create an additional window (the one that is used to enter the new geometry)
dialog = Toplevel(root)
# Add entry widgets for width and height to the new window
width_entry = tk.Entry(dialog)
height_entry = tk.Entry(dialog)
# Add a button to the new window that applies the given width and height
apply_button = Button(dialog, text = 'Apply geometry', command = lambda: canvas.geometry(width_entry.get()+'x'+height_entry.get()))
# Its not possible to get the geometry of a canvas in tkinter...so how do I change the size.
# display the entry boxes and button
width_entry.pack()
height_entry.pack()
apply_button.pack()
# start the tk mainloop
root.mainloop()
Please Assist me
The command you are looking for is canvas.config
Here, I have adjusted the given code:
import tkinter as tk
# create root window
root = tk.Tk()
# Create Canvas
canvas = tk.Canvas(root, width=50, height=50)
canvas.pack()
# Create an additional window (the one that is used to enter the new geometry)
dialog = tk.Toplevel(root)
# Add entry widgets for width and height to the new window
width_entry = tk.Entry(dialog)
height_entry = tk.Entry(dialog)
# Add a button to the new window that applies the given width and height
apply_button = tk.Button(dialog, text = 'Apply geometry', command = lambda: canvas.config(width=width_entry.get(), height=height_entry.get()))
# display the entry boxes and button
width_entry.pack()
height_entry.pack()
apply_button.pack()
# start the tk mainloop
root.mainloop()
I also changed a couple other things:
You imported * from tkinter, but for some items you still led with tk.; I changed them all to match that and switched the import to match as well. (You could still use *, but then just don't have the leading tk.s.)
The canvas was never packed so you could never see what was going on there.
One more suggestion, that line where you make the button is really long. Maybe make a function that does what the lambda does and assign its command to that function instead of a lambda. You can probably see that a line that long is even hard to read here much less if someone (maybe a future version of yourself) was to try to read your code, and edit it or make sense of it. Generally, try to keep all lines down to 80 characters.
Let us know if you have any more questions etc.

Change the color of an object after tkinter has been initiated

I am trying to make a circle in tkinter change colors after the window has been initiated. I've looked at this question, and I know how to change the colors after stating the variable. I'm trying to make a traffic light (much like the person in the question I looked at), but I can't update the color change after the screen comes up. This is what I have so far
root = tk.Tk()
canvas = tk.Canvas(root)
light_1 = canvas.create_oval(*coordinates here*, fill='green')
root.mainloop()
and to change the color use canvas.itemconfig(light_1, fill='blue')
and I can't just do a time.sleep(1) because then the root.mainloop() is only reached after i change the color. There is no visual feedback of it changing
You can't use time.sleep() anywhere in tkinter code because it blocks the tkinter mainloop from running. The solution is to add your code to the tkinter mainloop using the after method:
def change_color():
canvas.itemconfig(light_1, fill='blue')
root = tk.Tk()
canvas = tk.Canvas(root)
light_1 = canvas.create_oval(*coordinates here*, fill='green')
root.after(1000, change_color) # 'after' uses milliseconds, so 1,000 = 1 second
root.mainloop()

Categories