Why is my image appearing on the wrong window in Tkinter? - python

So I am trying to make a text-based game, but also want to incorporate images into it, I have a main menu, a window that is always open, and then a game window, that should have the image in, but for some reason, it appears in the menu window instead. Has anyone got any idea why?
def menu():
master = Tk()
master.geometry("350x300")
master.wm_iconbitmap("zombie.ico")
master.configure(background = '#484a2c')
master.title("Menu")
def game():
master = Tk()
master.geometry("800x500")
master.title("Game")
master.wm_iconbitmap("zombie.ico")
master.configure(background = '#484a2c')
image = PhotoImage(file="Kitchenimage.gif")
label5 = Label(image=image)
label5.image = image
label5.pack()
label = Label(master, text = "Zombie Mansion", background = '#484a2c',
font = ("AR CHRISTY", 30))
label.pack()
b = Button(master,text = "Play Game", height = 1, width = 10)
b.config(background = '#484a2c', activebackground = '#484a2c', font =
("AR CHRISTY", 14), command = get_username)
b.place(x = 120, y = 70)
mainloop()

"Why is my image appearing on the wrong window in Tkinter?"
Assuming you have another instance of Tk as what you refer to as main menu somewhere in your code that you're not showing us like:
main = Tk()
in addition to master = Tk() in your game method, then it's because when you instantiate widgets without passing a parent widget explicitly like in:
label5 = Label(image=image)
then the widget's parent defaults to the Tk instance whose mainloop is being run, in above case supposedly main's. By default widgets are shown under their parents, hence the reason.
Pass parent explicitly like:
label5 = Label(master=main, image=image)
or
label5 = Label(master, image=image)
In most cases, if not all cases, you shouldn't have multiple instances of Tk. If you require additional windows, please use Toplevel widget.

Related

How do i pause my code before displaying the label

In my code, I am trying to make a loading screen for a frogger game but for some reason I am encountering a problem where I display a picture and then do the .sleep function before displaying a label over the top of it however it displays both of them at the same time it just runs the code 1 second after it should, can anyone help?
Here is my code below:
from tkinter import *
import tkinter as tk
import time
window = Tk()
window.geometry("1300x899")
LoadingScreen = PhotoImage(file = "FroggerLoad.gif")
Loading = Label(master = window, image = LoadingScreen)
Loading.pack()
Loading.place(x = 65, y = 0)
time.sleep(1)
FroggerDisplay = Label(master = window, font ("ComicSans",100,"bold"),text = "Frogger")
FroggerDisplay.pack()
FroggerDisplay.place(x = 500, y = 300)
window.mainloop()
When you use time.sleep(1) before starting the window.mainloop(), the window is created only after 1 second, and the FroggerDisplay label will be created at the same time with it. So, you can't use time.sleep(seconds) now.However, you can use window.after(ms, func) method, and place into the function all the code between time.sleep(1) and window.mainloop(). Note, that unlike the time.sleep(seconds) you must give the time to window.after (the first argument) as milliseconds.Here is the edited code:
from tkinter import *
def create_fd_label():
frogger_display = Label(root, font=("ComicSans", 100, "bold"), text="Frogger") # create a label to display
frogger_display.place(x=500, y=300) # place the label for frogger display
root = Tk() # create the root window
root.geometry("1300x899") # set the root window's size
loading_screen = PhotoImage(file="FroggerLoad.gif") # create the "Loading" image
loading = Label(root, image=loading_screen) # create the label with the "Loading" image
loading.place(x=65, y=0) # place the label for loading screen
root.after(1000, create_fd_label) # root.after(ms, func)
root.mainloop() # start the root window's mainloop
PS: 1) Why do you use .pack(...) and then .place(...) methods at the same time - the first one (.pack(...) here) will be ignored by Tkinter.
2) It's better to use a Canvas widget for creating a game - unlike labels it supports transparency and simpler to use. For example:
from tkinter import *
root = Tk() # create the root window
root.geometry("1300x899") # set the root window's size
canv = Canvas(root) # create the Canvas widget
canv.pack(fill=BOTH, expand=YES) # and pack it on the screen
loading_screen = PhotoImage(file="FroggerLoad.gif") # open the "Loading" image
canv.create_image((65, 0), image=loading_screen) # create it on the Canvas
root.after(1000, lambda: canv.create_text((500, 300),
font=("ComicSans", 100, "bold"),
text="Frogger")) # root.after(ms, func)
root.mainloop() # start the root window's mainloop
Note: you might need to change coords with Canvas.

Adding Windows to Buttons on Tkinter GUI

I'm new to Python, I'm trying to add widgets in an window which can be used when we click on an button when in Tkinter GUI.
I'm unable to add an window into the GUI button and I'm doubtful about the Code which can be Implemented as well. I hope I could get some inputs on this.
I'm running on IDLE 3.6.3.I would be grateful if someone could point out the additions that could be made and the changes in the current code.
ConnectLogo=PhotoImage(file="Connect.png")
Connect = Button(win,image=ConnectLogo,text = "Connect", font = myFont,height =100 , width = 100,compound=TOP,bg = "orange")
Connect.grid(row=3,column=1,padx=50,pady=40)
FrequencyLogo=PhotoImage(file="Frequency.png")
Frequency = Button(win,image=FrequencyLogo, text = "Frequency", font = myFont, height = 100, width =180,compound=TOP,bg = "Yellow")
Frequency.grid(row=3,column=2,padx=10)
MaskLogo=PhotoImage(file="Mask.gif")
Mask = Button(win,image=MaskLogo, text = "Mask", font = myFont, height = 100, width =180,compound=TOP,bg = "yellow")
Mask.grid(row=6,column=2,padx=10)
You can make a function, which will implement TopLevel.
This creates a new window into which you can add widgets, add them inside the function.Inside the function you root becomes window
from tkinter import *
root = Tk()
def new_window():
window = TopLevel(root)
...widgets like label, entry etc
label = Label(window,....)
btn = Button(...., command = new_window)
btn.pack()...(anything)

I am trying to create buttons in tkinter

I am trying to create buttons in a program to take the user to other screens. I have created the images on labels but not sure on how to make them into functioning buttons that take users to another page. You can see in my code the 2 buttons i need are the search quote and new quote. Thank you
from tkinter import *
class Window():
def __init__(self,master): #constructor
self.master = master
self.master.title("Borras Roofing Quotation System") #sets title of window
self.master.geometry("2160x1440") #sets size of window
self.master.configure(background = "white") # sets background colour of window.
self.Borras = PhotoImage(file = "Borras.Logo.PNG") #sets up image
self.BorrasLabel = Label(self.master, image = self.Borras, bg = "white", width='1000', height= '500') #puts image onto label
self.BorrasLabel.pack()
self.newquote = PhotoImage(file = "Process_New_Quote_Button.PNG") #sets up image
self.newquoteLabel = Label(self.master, image = self.newquote, bg = "white") #puts image onto label
self.newquoteLabel.place(x = 200, y = 500)
self.searchquote = PhotoImage(file = "Search_Current_Quote_Button.PNG") #sets up image
self.searchquoteLabel = Label(self.master, image = self.searchquote, bg = "white") #puts image onto label
self.searchquoteLabel.place(x = 800, y = 500)
root = Tk()
userPassWindow = Window(root)
root.mainloop()
You can use the inheritance and make each window child of the Toplevel widget.
Example:
from Tkinter import *
class search(Toplevel):
# Just inherits TopLevel window
def __init__(self, parent, master=None):
Toplevel.__init__(self, master)
#Save parent reference to modify parent view from search view
self.parent = parent
class quote(Toplevel):
def __init__(self, parent, master=None):
self.parent = parent
Toplevel.__init__(self, master)
class Window():
def __init__(self,master): #constructor
self.master = master
self.master.title("Borras Roofing Quotation System") #sets title of window
self.master.geometry("400x440") #sets size of window
self.master.configure(background = "white") # sets background colour of window.
self.Borras = PhotoImage(file = "Borras.Logo.PNG") #sets up image
self.BorrasLabel = Label(self.master, image = self.Borras, bg = "white") #puts image onto label
self.BorrasLabel.place(x = 10, y = 50)
self.newquote = PhotoImage(file = "Process_New_Quote_Button.PNG") #sets up image
self.newquoteLabel = Label(self.master, image = self.newquote, bg = "white") #puts image onto label
self.newquoteLabel.place(x = 150, y = 50)
self.searchquote = PhotoImage(file = "Search_Current_Quote_Button.PNG") #sets up image
self.searchquoteLabel = Label(self.master, image = self.searchquote, bg = "white") #puts image onto label
self.searchquoteLabel.place(x = 300, y = 50)
search_quote = Button(text="Search quote", command=self.search)
quote = Button(text="Quote", command=self.quote)
search_quote.pack()
quote.pack()
def search(self):
#Pass parent reference 'self'
search(self)
def quote(self):
quote(self)
root = Tk()
userPassWindow = Window(root)
root.mainloop()
For a start you need to use instances of Button, not Label if you want to achieve anything by clicking on it. If you add
command = anyfunction
as an argument to a button then the function will be run when the button is pressed (the function can be declared either inside or outside the Class, depending on what scope you want). From there use the
.pack_forget()
or
.place_forget()
procedure to remove items (though this does NOT delete them) and pack, place or grid the new items in your "window". If you are looking for actual screens to pack and forget pack then you should use tkinter Frames. Here is a useful link that will show you how to use each widget correctly:
http://effbot.org/tkinterbook

How to make a button open a new window?

I am making a simple GUI that starts with a main menu them the user can click a button to proceed to a new window which has a picture of a keyboard and the user can press key on their keyboard to play the paino. Right now I cant figure out how to make a button that when pressed closes the main menu (labeled mainMenu()) and open the game menu (playGame).
import tkinter
from tkinter import *
class mainMenu:
def _init_(self, master):
frame = Frame(master)
frame.pack()
self.quitButton = Button(frame, text = "Quit", command = frame.quit)
self.quitButton.pack(side = LEFT)
self.proceedButton = Button(frame, text = "Play", command = playGame)
self.proceedButton.pack(side = LEFT)
def playGame(self):
frame.quit
gameMenu()
def gameMenu(self):
root = Tk()
b = mainMenu(root)
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomeFrame.pack(side = BOTTOM)
photo = PhotoImage(file = "piano.png")
label = Label(root, image = photo)
label.pack()
root.mainloop()
You'll have to forgive me for removing your class but I've never personally worked with classes in python before. However I seem to have you code working to some degree.
import tkinter
from tkinter import *
def playGame():
frame.quit
gameMenu()
def gameMenu():
b = mainMenu(root)
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side = BOTTOM)
photo = PhotoImage(file = "piano.png")
label = Label(root, image = photo)
label.pack()
root=Tk()
frame = Frame(root)
frame.pack()
quitButton = Button(frame, text = "Quit", command = frame.quit)
quitButton.pack(side = LEFT)
proceedButton = Button(frame, text = "Play", command = playGame)
proceedButton.pack(side = LEFT)
root.mainloop()
The main problem you had was that you were using both root and master. When declaring the main window in tkinter you normally use either root = Tk() or master = Tk() either one is acceptable, personally I use master. This variable contains the main window that everything else is placed into. You also hadn't put Tk() into any variable, meaning that when you hit root.mainloop() there was nothing to enter the main loop, this was because you were trying to declare root = Tk() inside gameMenu, which wasn't getting called in your program.
If you want to open windows within tkinter it's probably easier to write something like this:
from tkinter import *
master = Tk() #Declaring of main window
def ProceedButtonCommand(mainframe, master): #Command to attach to proceed button
mainframe.destroy()
DrawSecondScreen(master) #This line is what lets the command tied to the button call up the second screen
def QuitButtonCommand(master):
master.destroy()
def DrawFirstScreen(master):
mainframe = Frame(master) #This is a way to semi-cheat when drawing new screens, destroying a frame below master frame clears everything from the screen without having to redraw the window, giving the illusion of one seamless transition
ProceedButton = Button(mainframe, text="Proceed", command=lambda: ProceedButtonCommand(mainframe, master)) #Lambda just allows you to pass variables with the command
QuitButton = Button(mainframe, text = "Quit", command=lambda: QuitButtonCommand(master))
mainframe.pack()
ProceedButton.pack()
QuitButton.pack()
def DrawSecondScreen(master):
mainframe = Frame(master)
Label1 = Label(mainframe, text="Temp")
mainframe.pack()
Label1.pack()
DrawFirstScreen(master)
master.mainloop() #The mainloop handles all the events that occur in a tkinter window, from button pressing to the commands that a button runs, very important
This little script just draws a screen with two buttons, one draws a new screen with the text "temp" on it and the other button closes the master window.
In the future it's probably a better idea to ask a friend who is experienced in programming to help with this kind of stuff. Get talking on some computing forums, I'm sure you'll find a group of sharing and fixing code quickly.

bring window to top level

I want to present several questions, one after another. The first question is shown as I like, with the cursor set in the entry field. Then I destroy the window and call the function again to create a new window. This time the window is not shown in the front and therefore I first have to click on the screen in order to have the cursor set to the entry field. Also the escape key does not work until I click on the screen to bring the window to the top. I'd be very happy for your help!
Thank you in advance!
Here's my code:
from Tkinter import *
def text_input_restricted(fn,question, nr_letters, limit, len_min, len_max,keys, justify):
class MyApp():
def validate(root, S):
return all(c in keys for c in S)
def __init__(self, q= None):
#save response after "next"-button has been clicked
def okClicked():
lines = e.get()
if len_min < len(lines) < len_max:
lines = unicode(lines).encode('utf-8')
datFile = open(fn, "a")
datFile.write(" '%s'"%(lines))
datFile.close()
self.root.destroy()
self.root = Tk()
vcmd = (self.root.register(self.validate), '%S')
#quit if escape-key has been pressed
self.root.bind('<Escape>', lambda q: quit())
#colors
color = '#%02x%02x%02x' % (200, 200, 200)
self.root.configure(bg=color)
#set window size to screen size
RWidth=MAXX
RHeight=MAXY
self.root.geometry(("%dx%d")%(RWidth,RHeight))
#remove buttons (cross, minimize, maximize)
self.root.overrideredirect(1)
#remove title
self.root.title("")
#item
labelWidget = Label(self.root,text=question, font=("Arial", int(0.02*MAXX)), bd=5, bg=color, justify="center")
labelWidget.place(x=0, y=RHeight/40,width=RWidth)
#"next"-button
ok_width = RWidth/15
ok_height = RWidth/15
okWidget = Button(self.root, text= "next", command = okClicked, font=("Arial",int(0.015*MAXX)), bd=5, justify="center")
okWidget.place(x=RWidth/2-ok_width/2,y=13*RHeight/40, width=ok_width,height=ok_height)
def callback(sv):
c = sv.get()[0:limit]
sv.set(c)
sv = StringVar()
width=nr_letters * int(0.02*MAXX)*1.3
sv.trace("w", lambda name, index, mode, sv=sv: callback(sv))
e = Entry(self.root, textvariable=sv,font=("Arial", int(0.02*MAXX)),justify=justify,validate="key", validatecommand=vcmd)
e.place(x=RWidth/2-width/2, y=9*RHeight/40, width=width)
#show cursor
e.focus_set()
self.root.mainloop()
MyApp()
MAXX=1366
MAXY=768
fn = "D:/test.dat"
text_input_restricted(fn = fn, question=u"f for female, m for male", nr_letters=1, limit =1, len_min =0, len_max=2, keys = 'fm', justify="center")
text_input_restricted(fn = fn, question="How old are you?", nr_letters=2,limit=2, len_min = 1, len_max = 3, keys = '1234567890',justify="center")
In Tk you use the raise command to bring a window to the front of the Z-order. However, raise is a keyword in Python so this has been renamed to lift. Provided your application is still the foreground application you can call the lift() method on a toplevel widget. If the application is not the foreground application then this will raise the window but only above other windows from the same application. On Windows this causes the taskbar icon for your application to start flashing.
You might do better to destroy the contents of the toplevel and replace them. Or even better - create a number of frames holding each 'page' of your application and toggle the visibility of each frame by packing and pack_forgetting (or grid and grid forget). This will avoid loosing the focus completely - you can just set the focus onto the first widget of each frame as you make it visible.

Categories