tkinter canvas image is not displayed in class - python

I am trying to display an image in python using the tkinter canvas option. However, if I input it in a class, like below, it doesn't give an error but also doesn't show my image. The buttons are displayed correctly though. Also, if I take the code for generating this image out of the class it works correctly. I can't seem to find out what the problem is.
import Tkinter as tk
from Tkinter import *
class Board(tk.Frame):
def __init__(self,parent):
frame = Frame(parent)
frame.pack()
tk.Frame.__init__(self,parent)
frame2 = Frame(frame)
frame2.pack()
c=Canvas(frame2)
c.pack(expand=YES,fill=BOTH)
background=PhotoImage(file='Board.gif')
c.create_image(100,100,image=background,anchor='nw')
button = Button(frame, text="Next turn", command=self.next_turn)
button.pack()
button = Button(frame, text="Roll the dice", command=self.roll)
button.pack()
....
root = Tk()
board = Board(root)
board.pack()
root.mainloop()

You have to keep a reference to the PhotoImage. This is just and example (you can also use self.background instead of c.background):
c = Canvas(frame2)
c.pack(expand=YES,fill=BOTH)
c.background = PhotoImage(file='Board.gif')
c.create_image(100,100,image=c.background,anchor='nw')

Related

How to open the initial window in tkinter again?

I have a following question. I want to make a button in tkinter that will delete existing changes and the window will looks like the initial window.
This is my initial Window 1:
This is how the window looks like when I click on the first two buttons, Window 2:
Now I would like to click on the "Zpět" button and I want to see Window 1 again.
Here is my code:
import tkinter as tk
root = tk.Tk()
home_frame = tk.Frame(root)
home_frame.grid(row=0, column=0, sticky="news")
def raise_new_payment():
tk.Label(text=f"Stav bilance k 2021-09-09").grid()
def back():
"""I would like to this function to clean everything."""
tk.Label().destroy()
platba = tk.Button(
home_frame,
text="Zadej novou platbu",
command=lambda: raise_new_payment(),
)
platba.pack(pady=10)
zpet = tk.Button(
home_frame,
text="Zpět",
command=back,
)
zpet.pack(pady=10)
I don't know how to use the back() function. I tried to delete the tk.Label as created in raise_new_payment(), but it did not work. Can you help me please? Thanks a lot.
I would suggest you create the label once and don't call .pack() on it first, i.e. it is not visible initially.
Then update it inside raise_new_payment() and call .pack() to show it.
You can call .pack_forget() to hide it again inside back().
import tkinter as tk
root = tk.Tk()
home_frame = tk.Frame(root)
home_frame.grid(row=0, column=0, sticky="news")
def raise_new_payment():
# update label and show it
lbl.config(text=f"Stav bilance k 2021-09-09")
lbl.pack()
def back():
# hide the label
lbl.pack_forget()
platba = tk.Button(
home_frame,
text="Zadej novou platbu",
command=lambda: raise_new_payment(),
)
platba.pack(pady=10)
zpet = tk.Button(
home_frame,
text="Zpět",
command=back,
)
zpet.pack(pady=10)
# create the label and initially hide it
lbl = tk.Label(home_frame)
root.mainloop()

How to pass a class with Toplevel widget in Tkinter

I have a readymade game(2048), where the game starts without a welcome window, so, I have just made a welcome window with a bunch of buttons like New Game and AI mode, now when I click the New Game button, I expect to get a new window where the game can be played. However, the game displays at the bottom of the main window, and another window that is supposed to display the actual game displays nothing.
# mainwindow.py file:
from tkinter import *
from PIL import ImageTk, Image
import game_2048
root = Tk()
root.iconbitmap('unnamed.ico')
root.title('2048')
bg = ImageTk.PhotoImage(Image.open("welcome.png"))
my_canvas = Canvas(root, width=780, height=550)
my_canvas.grid()
my_canvas.create_image(0, 0, image=bg, anchor=NW)
button1 = Button(root, text="New Game", fg="black", bg="#ddf0d0", padx=3,
pady=3, font=('Helvetica', '12', 'bold'), activebackground="#94d3c3", command=lambda: game_2048.mains(root)
)
button2 = Button(root, text="AI Mode", fg="black", bg="#ddf0d0",
padx=3, pady=3, font=('Helveica', '12', 'bold'), activebackground="#94d3c3")
button1_window = my_canvas.create_window(10, 10, anchor=NW, window=button1)
button2_window = my_canvas.create_window(120, 10, anchor=NW, window=button2)
root.mainloop()
And I have tried to modify the game_2048 file i.e. 2048 game like this:
def mains(root):
Top = Toplevel(root)
l1 = Button(Top, command=lambda:Game())
l1.pack()
class Game(tkinter.Frame):
def __init__(self):
tkinter.Frame.__init__(self)
self.grid()
self.master.title('2048')
self.main_grid = tkinter.Frame(
self, bg=c.GRID_COLOR, bd=3, width=400, height=400)
self.main_grid.grid(pady=(80, 0))
self.make_GUI()
self.start_game()
self.master.bind("<Left>", self.left)
self.master.bind("<Right>", self.right)
self.master.bind("<Up>", self.up)
self.master.bind("<Down>", self.down)
self.mainloop()
if __name__ == "__main__":
mains()
I am pretty sure that I have made some mistakes in the mains() function as a result of which I am not getting the desired output. So my question is what should I do to rectify these mistakes?
Here are the changes I made to your code:
Removed import mainwindow from game_2048.py, as it will lead to circular import calling the functions twice.
You created a class inheriting from a Frame, this frame is just like any other tkinter widget, requires to be placed in the window using geometric manager, like pack()/grid()/place(), you did not do that
I also destroyed the root window before creating another new root window. Also note that instead of using Toplevel, I used Tk. This is done, so that closing the game window will close the app. But if using Toplevel, you will have to close the menu window too.
from tkinter import *
import tkinter
import random
import colors as c
def mains(root):
root.destroy()
root = Tk()
def init(root):
l1.destroy()
game = Game(root)
game.pack()
l1 = Button(root, text='Start Game',command=lambda: init(root))
l1.pack()
class Game(tkinter.Frame):
def __init__(self, parent):
tkinter.Frame.__init__(self, parent)
.......
But if you were to ask me, I would not go for such structure, but this will work here too. Understand this, work on it, implement your own structure that does not call more than one Tk().

How can I place a label of top of this frame? Tkinter

I am trying to place a label on top of a Frame, which is inside a 'Notebook' tab.
But when I run this code, the label always ends up in the center of the frame.
from tkinter import *
from tkinter import ttk
class Window:
def __init__(self,master):
self.master = master
master.title("Title")
master.resizable(1,1)
master.geometry('500x400')
self.load_UI()
def load_UI(self):
self.tabOptions = ttk.Notebook(self.master )
self.tab1 = Frame(self.tabOptions, padx=130, pady=80, bg='white')
self.tabOptions.add(self.tab1, text="Add Files")
self.tabOptions_AddFile()
self.tabOptions.pack()
def tabOptions_AddFile(self):
self.label = Label(self.tab1, text="Why is this in the center of the frame?")
self.label.grid(row=0, column=0)
root = Tk()
app = Window(root)
root.mainloop()
I tried to place the label using: pack(), grid(), place(). I also tried to place the label before adding the frame to the Notebook but it still looks the same :(
I am using python 3 btw.
This is because your Frame is padded in the line self.tab1 = Frame(self.tabOptions, padx=130, pady=80, bg='white'). Your Frame is here:
Just remove padx=130, pady=80 and all works. But to keep the size of tabOptions, replace
self.tabOptions.pack()
by
self.tabOptions.pack(fill=BOTH, expand=True)

Tkinter button widget can not locate image, err image doesn't exist

When trying to place an image in a button, I get an error "_tkinter.TclError: image "pyimage1" doesn't exist". The image does exist though because I used it on another button and it works there.
When I try to use the image again on a second button that's when the error occurs.
I have tried removing the image and the button works. Tried using the image on anther button and it works for one button only.
from tkinter import ttk
from tkinter import Tk, PhotoImage
class Window(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
def main():
root = Tk()
style = ttk.Style(root)
style.theme_use('clam')
root2 = Tk()
style = ttk.Style(root2)
style.theme_use('alt')
root3 = Tk()
style = ttk.Style(root3)
style.theme_use('classic')
root4 = Window()
style = ttk.Style(root4)
style.theme_use('default')
icon = PhotoImage(file='test.gif')
# This line works, the image appears on the button.
ttk.Button(root, image=icon, compound='left', text="Quit", command=root.destroy).pack()
# This line works with out the image.
ttk.Button(root2, compound='left', text="Quit", command=root2.destroy).pack()
# This line does not work with an image.
# if the line below is un-commented the code does not work, the error I get is below.
# _tkinter.TclError: image "pyimage1" doesn't exist
# ttk.Button(root2, image=icon, compound='left', text="Quit", command=root2.destroy).pack()
ttk.Button(root3, text="Quit", command=root3.destroy).pack()
ttk.Button(root4, text="Quit", command=root4.destroy).pack()
root.mainloop()
if __name__ == '__main__':
main()
I want images on all buttons.
I can only get it to work for one button only.
You're going to have to create another PhotoImage for each window with the master keyword:
icon = PhotoImage(master=root, file='test.gif')
icon2 = PhotoImage(master=root2, file='test.gif')
icon3 = PhotoImage(master=root3, file='test.gif')
icon4 = PhotoImage(master=root4, file='test.gif')
And then use each icon for the corresponding button:
ttk.Button(root, image=icon, compound='left', text='Quit', command=root.destroy).pack()
ttk.Button(root2, image=icon2, text='Quit', command=root2.destroy).pack()
ttk.Button(root3, image=icon3, text='Quit', command=root3.destroy).pack()
ttk.Button(root4, image=icon4, text='Quit', command=root4.destroy).pack()
Hope this works for you.

Buttons not appearing below image in python GUI

I am developing a GUI on Python and I have the following problem: I want to have the picture at the top of the window and buttons right underneath it. I am using the Tkinter module and whatever geometry I use (place, pack or grid) the buttons don't move. The are only displayed if I move the image using grid to row 1 (which is the second row), otherwise they don't appear at all. Here is the code I am using for now. For reference the picture has dimensions of 291x87 pixels.
import Tkinter
from Tkinter import *
def main():
window =Tk()
window.geometry("300x300")
window.title("Dienes Blocks Application")
window.iconbitmap(default='favicon.ico')
app = HomeScreen(window)
window.mainloop()
class HomeScreen(Frame):
def __init__(self, master):
Frame.__init__(self,master)
self.create_buttons()
self.sparx_head()
def sparx_head(self):
self.grid()
photo = Tkinter.PhotoImage(file="logosmall.gif")
sparx_header = Label(image=photo)
sparx_header.image = photo # keep a reference!
sparx_header.grid(column=0, row=0, columnspan=2, rowspan=2, sticky='NSEW')
def create_buttons(self):
self.grid()
#teacher button
teacher_button = Tkinter.Button(self, text="Teacher")
teacher_button.grid(column=0, row=10)
# student button
student_button = Tkinter.Button(self, text="Student")
student_button.grid(column=2, row=10)
# prototype button
prototype_button = Tkinter.Button(self, text="Prototype")
prototype_button.grid(column=1, row=10)
if __name__ == "__main__":
main()
You just need to use self in the image label:
sparx_header = Label(self,image=photo)
They were not having the same parent & that's why you were having this problem

Categories

Resources