Displaying images in a specific frame in Python using TKinter - python

I am trying to display images in my game, which in time will correspond to rooms.
I have three main frames and I want to display images in the one called 'frame 3', but I am not unable to get the picture itself to display!
I made a method called RoomImages which is supposed to handle the roomImages. I have called this method in my constructormethod for the whole App class.
It displays no error messages and therefore I am unsure where the missing logic is.
I have attached a picture of what the output shows:
Output
import tkinter as tk
from Game import Game
from tkinter import messagebox
from PIL import ImageTk, Image
class App():
# Creates a Frame for the application
# and populates the GUI ...
def __init__(self, root):
#super().__init__(master=win)
self.game = Game()
#A menubar with the options Quit' which destroys the window
# and 'about' which displays a message box with the info from the method showAbout
menubar = tk.Menu()
menubar.add_command(label="Quit", command=root.destroy)
menubar.add_command(label="About", command=self.showAbout)
root.config(menu=menubar)
# Create two frames owned by the window root
# In order to use multiple layout managers, the frames
# cannot share a parent frame. Here both frames are owned
# by a top level instance root.
self.frame1 = tk.Frame(root, width=600, height=250, bg='WHITE', borderwidth=2)
self.frame1.pack_propagate(0) # Prevents resizing
self.frame2 = tk.Frame(root, width=600, height=150, bg='LIGHT GREY', borderwidth=2, padx=175)
self.frame2.grid_propagate(0) # Prevents resizing
self.frame3 = tk.Frame(root, width=600, height=250, bg='LIGHT BLUE', borderwidth=2, padx=275)
self.frame3.grid_propagate(0) # Prevents resizing
# This packs both frames into the root window ...
self.frame1.pack()
self.frame2.pack()
self.frame3.pack()
#image canvas for frame3 to display the current room
self.canvas_for_image = tk.Canvas(self.frame3, bg='LIGHT GREY', height=250, width=600, borderwidth=0, highlightthickness=0)
self.canvas_for_image.grid(row=0, column=0, sticky='nesw', padx=0, pady=0)
#self.canvas_for_image.pack(expand=YES, fill=BOTH)
self.frame3.columnconfigure(0, pad=5)
self.frame3.columnconfigure(1, pad=5)
self.frame3.rowconfigure(0, pad=5)
self.frame3.rowconfigure(1, pad=5)
#make a gridstructure for frame2 to be able to precisely place my buttons.
self.frame2.columnconfigure(0, pad=5)
self.frame2.columnconfigure(1, pad=5)
self.frame2.columnconfigure(2, pad=5)
self.frame2.columnconfigure(3, pad=5)
self.frame2.columnconfigure(4, pad=5)
self.frame2.columnconfigure(5, pad=5)
self.frame2.rowconfigure(0, pad=5)
self.frame2.rowconfigure(1, pad=5)
self.frame2.rowconfigure(2, pad=5)
self.frame2.rowconfigure(3, pad=5)
# Now add some useful widgets ...
self.textArea1 = tk.Label(self.frame1, text='')
self.textArea1.pack()
self.cmdArea = tk.Entry(self.frame2, text='')
self.cmdArea.grid(row = 3, column = 1)
self.buildGUI()
self.roomImages()
def showAbout(self):
"""uses the messagebox import to display info about the game"""
messagebox.showinfo("About", "A classic whodunnit where you have to find out who the murder is!")
def buildGUI(self):
self.doCmd = tk.Button(self.frame2, text='Run command',
fg='black', bg='blue',
command=self.doCommand)
self.doCmd.grid(row = 1, column = 1)
self.goDown = tk.Button(self.frame2, text='Down',
fg='black', bg='red',
command=self.processDownCommand)
self.goDown.grid(row=2, column=1)
self.goUp = tk.Button(self.frame2, text='Up',
fg='black', bg='red',
command=self.processUpCommand)
self.goUp.grid(row =0, column=1)
self.goLeft = tk.Button(self.frame2, text='Left',
fg='black', bg='red',
command=self.processLeftCommand)
self.goLeft.grid(row=1,column = 0)
self.goRight = tk.Button(self.frame2, text='Right',
fg='black', bg='red',
command=self.processRightCommand)
self.goRight.grid(row=1, column =2)
self.help = tk.Button(self.frame2, text='Help',
fg='black', bg='green',
command=self.processHelpCommand)
self.help.grid(row=1, column=4)
self.textArea1.configure(text=self.game.printWelcome())
def roomImages(self):
self.imageDict = {'apple': 'apple.png', 'banana': 'banana.png', 'bar': 'bar.png', 'cherries': 'cherries.png',
'grapes': 'grapes.png', 'lemon': 'lemon.png', 'melon': 'melon.png', 'orange': 'orange.png'}
self.apple = 'apple'
self.apple = f'images/{self.imageDict[self.apple]}'
#adding images
self.r1 = ImageTk.PhotoImage(Image.open(self.apple))
self.r1Label = tk.Label(self.frame3, image=self.r1)
def main():
win = tk.Tk() # Create a window
win.title("Adventure World with GUI") # Set window title
win.geometry("700x400") # Set window size
win.resizable(False, False) # Both x and y dimensions ...
# Create the GUI as a Frame
# and attach it to the window ...
myApp = App(win)
# Call the GUI mainloop ...
win.mainloop()
if __name__ == "__main__":
main()

Related

Python tkinker resitze Canvas

I have an Python3 Tkinter Programm. I have 3 Frames in the Main Window and in one Frame an canvas with scroll Option - now i want resitze the Canvas Area .
Now if i resize it moves the Scroll Bar for Y out the Window and the scrollbar for x works also not as expected (get bigger but slide area don't change)
How i Mange it to resize an Canvas in an grid Layout - The Window must be the same size , the Scrollbas must be updatet and the Canvas Plane must be bigger.
an excerpt from my code:
import tkinter as tk
def menu_build():
caninfo[0] += 10
cangui.configure(width = caninfo[0])
#cangui.configure(scrollregion=cangui.bbox("all"))
def gui():
master = tk.Tk()
master.title( "Easy Switch" )
master.geometry("480x320")
frametop = tk.Frame(master, bg="blue", bd=2)
frametop.grid(column=0,row=0)
frameex = tk.Frame(master, bg="yellow", bd=2)
frameex.grid(column=1,row=1)
framegui = tk.Frame(master, bg="red", bd=2)
framegui.grid(column=0, columnspan=2, row=1)
menu = tk.Menu(master)
master.config(menu=menu)
filemenu = tk.Menu(menu)
menu.add_cascade(label="Config", menu=filemenu)
filemenu.add_command(label="Resize",command=menu_build)
global cangui
cangui = tk.Canvas(framegui, width=385, height=250)
#caninfo = [385,250]
cangui.grid(row=1, column=2)
scroll_x = tk.Scrollbar(framegui, orient="horizontal", command=cangui.xview)
scroll_x.grid(row=2, column=2, sticky="ew")
scroll_y = tk.Scrollbar(framegui, orient="vertical", command=cangui.yview)
scroll_y.grid(row=1, column=3, sticky="ns")
cangui.configure(yscrollcommand=scroll_y.set,xscrollcommand=scroll_x.set)
cangui.configure(scrollregion=cangui.bbox("all"))
cwcb = tk.Checkbutton(framegui, text="ccw").grid(row=2,column=0)
cangui.create_arc(90,90,110,110,style=tk.PIESLICE,width=4,start=0,extent=300)
master.mainloop()
global caninfo
caninfo = [385,250]
if __name__ == "__main__":
gui()
no need to resize the canvas Area
wrote an extra funktion
win = [int(cangui.cget("width")),int(cangui.cget("height"))]
draw_xy = cangui.bbox("all")
swin = (min(0,draw_xy[0]),min(0,draw_xy[1]),max(draw_xy[2],win[0]),max(draw_xy[3],win[1]))
cangui.configure(scrollregion=swin)
reason: canvas.bbox("all") gives only the positon from most upper/left grafic and i want 0/0

Tkinter create a hidden frame

I'm creating a GUI whose window will consists of a few frames.
I need to pack many different widgets in each frame so if all are shown it will occupy a lot of space.
The idea is that each frame will be revealed/hidden with the push of a button.
I'm able to hide and reveal each frame using buttons, however I'd like those frame to start as hidden.
Is there a way to do that?
Here's a code that hides/reveals the frames.
import tkinter as tk
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
import os
# Method to make Label(Widget) invisible
def hide_frame(frame):
# This will remove the widget
frame.grid_remove()
# Method to make Label(widget) visible
def show_frame(frame):
# This will recover the widget
frame.grid()
#____________________________________________________________________________________________
#This will be the main window
window = tk.Tk()
window.geometry('500x500')
window.title("daq")
#____________________________________________________________________________________________
#Upper frame
frame_logo = Frame(window)
#____________________________________________________________________________________________
#Lower frame
frame_main = Frame(window)
frame_main.place(rely=0.10, relx=0.0, relwidth=1.0)
#Create a tabcontrol
tabControl = ttk.Notebook(frame_main)
tabControl.grid(column=0, row=1)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Digitizer tab
tab_Digitizer = ttk.Frame(tabControl)
tabControl.add(tab_Digitizer, text=' Digitizer ')
digitizer_tab_dummy_label = Label(tab_Digitizer, text="")
digitizer_tab_dummy_label.grid(column=0, row=0)
#General board settings
lbl_general_board_registers = Label(tab_Digitizer,
text="General board registers",
font='bold')
lbl_general_board_registers.grid(column=0, row=1, sticky=W)
frame_general_board_registers = Frame(tab_Digitizer)
frame_general_board_registers.grid(column=0, row=2)
btn_hide_general_board_registers = Button(tab_Digitizer, text="Hide", fg="red", command=lambda: hide_frame(frame_general_board_registers) )
btn_hide_general_board_registers.grid(column=1, row=1)
btn_show_general_board_registers = Button(tab_Digitizer, text="Show", fg="green", command=lambda: show_frame(frame_general_board_registers))
btn_show_general_board_registers.grid(column=2, row=1)
lbl_threshold1 = Label(frame_general_board_registers, text="Threshold1")
lbl_threshold1.grid(column=1, row=0)
lbl_trigger1 = Label(frame_general_board_registers, text="Trigger1")
lbl_trigger1.grid(column=1, row=1)
#Channel settings
lbl_channel_registers = Label(tab_Digitizer,
text="Channel registers",
font='bold')
lbl_channel_registers.grid(column=0, row=3, sticky=W)
frame_channel_registers = Frame(tab_Digitizer)
frame_channel_registers.grid(column=0, row=4)
btn_hide_channel_registers = Button(tab_Digitizer, text="Hide", fg="red", command=lambda: hide_frame(frame_channel_registers) )
btn_hide_channel_registers.grid(column=1, row=3)
btn_show_channel_registers = Button(tab_Digitizer, text="Show", fg="green", command=lambda: show_frame(frame_channel_registers))
btn_show_channel_registers.grid(column=2, row=3)
lbl_threshold = Label(frame_channel_registers, text="Threshold")
lbl_threshold.grid(column=1, row=0)
lbl_trigger = Label(frame_channel_registers, text="Trigger")
lbl_trigger.grid(column=1, row=1)
#Misc settings
lbl_misc_registers = Label(tab_Digitizer,
text="Misc settings",
font='bold')
lbl_misc_registers.grid(column=0, row=5, sticky=W)
frame_misc_registers = Frame(tab_Digitizer)
frame_misc_registers.grid(column=0, row=6)
#_________________________________________________________________________________________________
tab_SignalViewer = ttk.Frame(tabControl)
tabControl.add(tab_SignalViewer, text=' Signal Viewer ')
#tabControl.grid(column=0, row=1)
#This keeps the window open - has to be at the end
window.mainloop()

How to expand buttons and labels to fill the x axis in python tkinter?

This is a part of code from my school project.
from tkinter import *
from tkinter.font import Font
class student_window():
def __init__(self, master):
self.student_win = master
#window = Toplevel(self.master)
self.student_win.geometry("1280x720")
self.header1Font = Font(family='Helvetica', size=20)
self.optionFont = Font(family='Sans Serrif', size=20)
self.student_win.focus()
self.show_window()
def show_window(self):
print("ookk")
self.student_win.title("Student Window")
self.option_frame = Frame(self.student_win, width=200, height=720)
lbl_header = Label(self.option_frame,text="EXAMINATION", font=self.header1Font, fg='white', bg='#172D44').grid(row=0,column=0, sticky=NSEW)
lbl_welcome = Label(self.option_frame, text="Welcome,", fg='#E9F1F7', bg='#2A3F54').grid(row=1,column=0)
lbl_username = Label(self.option_frame, text="Username", fg='white', bg='#2A3F54').grid(row=2,column=0)
lbl_header2 = Label(self.option_frame, text="STUDENT CORNER", fg='white', bg='#2A3F54').grid(row=3, column=0)
self.btn_tests = Button(self.option_frame, text="Attempt Exam", fg='#E9F1F7', bg='#35495D', relief=FLAT)
self.btn_tests.grid(row=4,column=0, sticky=NSEW)
self.btn_attempts = Button(self.option_frame, text="Attempts", fg='#E9F1F7', bg='#2A3F54', relief=FLAT)
self.btn_attempts.grid(row=5, column=0, sticky=NSEW)
self.btn_result = Button(self.option_frame, text="Result", fg='#E9F1F7', bg='#2A3F54', relief=FLAT)
self.btn_result.grid(row=6, column=0, sticky=NSEW)
self.btn_goBack = Button(self.option_frame, text="Go Back", fg='#E9F1F7', bg='#2A3F54', relief=FLAT)
self.btn_goBack.grid(row=7, column=0, sticky=NSEW)
self.option_frame.configure(bg='#2A3F54')
self.option_frame.grid(row=0, column=0)
self.option_frame.grid_propagate(0)
self.main_frame = Frame(self.student_win, width=880, height=720)
self.main_result_frame = Frame(self.main_frame)
self.main_result_frame.grid(row=0,column=0)
self.attempts_frame = Frame(self.main_frame)
self.attempts_frame.grid(row=0, column=0)
self.test_frame = Frame(self.main_frame)
lbl_test = Label(self.test_frame, text="In test frame").pack()
self.test_frame.grid(row=0,column=0)
self.main_frame.grid(row=0,column=1)
self.main_frame.grid_propagate(0)
self.info_frame = Frame(self.student_win, width=200, height=720)
self.btn_username = Button(self.info_frame, text="Username", relief=FLAT)
self.btn_username.grid(row=0,column=0)
self.userInfo_frame = Frame(self.info_frame)
self.info_frame.grid(row=0, column=2)
self.info_frame.grid_propagate(0)
root = Tk()
student_window(root)
root.mainloop()
And it looks something like this.
The Student Panel for my project
The whole window is divided into three frames and want to expand each label and button of the left frame(self.option_frame) to fill it horizontally. I tried doing sticky=EW and sticky=NSEW but still some space is left. How do I fix that?
You need to call self.option_frame.columnconfigure(0, weight=1) to make column 0 to use all the available horizontal space.
I was just trying some things and what I have found to be working is to make the label width bigger than than the frame then anchoring the text to the left.

Python tkiner, two text boxes with x and y scrollbars for both

I am trying to make a gui that has two separate text outputs with horizontal and vertical scollbars for each text box that are fixed to the right and bottom edges of each respective text windows. I am struggling with how to do this with the tkinter grid and any help would be appreciated.
import tkinter as tk
class WeatherGUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# Horizontal (x) Scroll bar
self.xscrollbar = tk.Scrollbar(self, orient="horizontal")
self.xscrollbar.grid(column=5, row=10, sticky="we")
# Vertical (y) Scroll Bar
self.yscrollbar = tk.Scrollbar(self)
self.yscrollbar.grid(column=5, row=10, sticky='ns')
self.xscrollbar2 = tk.Scrollbar(self, orient="horizontal")
self.xscrollbar2.grid(column=9, row=10, sticky="we")
# Vertical (y) Scroll Bar
self.yscrollbar2 = tk.Scrollbar(self)
self.yscrollbar2.grid(column=9, row=10, sticky='ns')
self.NSW_actual_text = tk.Text(self, width=50, wrap = "none", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set,)
self.NSW_actual_text.grid(column=0, columnspan=4, row= 8,padx=(20, 10))
self.NSW_forecast_text = tk.Text(self, width=50, wrap = "none", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set)
self.NSW_forecast_text.grid(column=8, columnspan=4, row= 8,padx=(20, 10))
self.xscrollbar.config(command=self.NSW_actual_text.xview)
self.yscrollbar.config(command=self.NSW_actual_text.yview)
self.xscrollbar2.config(command=self.NSW_forecast_text.xview)
self.yscrollbar2.config(command=self.NSW_forecast_text.yview)
self.btn1 = tk.Button(self, text="Generate NWS Actual", command=self.GenerateNWSActual)
self.btn1.grid(column=1, row=0)
self.btn2 = tk.Button(self, text="Generate NWS Forecast", command=self.GenerateNWSForecast)
self.btn2.grid(column=10, row=0)
def GenerateNWSActual(self):
self.NSW_actual_text.insert('1.0', "This is where actual weather would go")
def GenerateNWSForecast(self):
self.NSW_forecast_text.insert('1.0', "this is where forecast weather would go")
app = WeatherGUI()
app.mainloop()
The following example allows you to attach two functional scrollbars (x, y) to a Text widget
from tkinter import *
# Create Window
root = Tk()
# Create ScrollBars
xScrollbar = Scrollbar(root, orient=HORIZONTAL)
yScrollbar = Scrollbar(root, orient=VERTICAL)
# Create Text Widget with scroll commands
TextWidget = Text(root, xscrollcommand=xScrollbar, yscrollcommand=yScrollbar)
# Package Componets
xScrollbar.pack(side=BOTTOM, fill=X)
yScrollbar.pack(side=RIGHT, fill=Y)
TextWidget.pack(fill=BOTH, expand=20)
# Assign Scrollbars with TextWidget
xScollbar.config(command=TextWidget.xview)
yScollbar.config(command=TextWidget.yview)
You can use this examble for both of your TextWidgets in your weather application.

Tkinter building windows similar to Root

I am currently working on Tkinter codes. I happen to need to create new windows exactly similar to root but my codes do not perfectly work well. The title does not appear on the new windows. This is an excerpt:
from tkinter import *
#New Window
def New_page():
window()
#Main Window
def window():
window = Tk()
window.resizable(0,0)
window.configure(background='grey')
window.state('zoomed')
window.geometry("2000x4000")
#Title Frame
TITLE_FRAME = Frame(window, relief = GROOVE, bg = "black", width=2000, height=160).grid(row=0, column=0, columnspan = 150, rowspan = 30, sticky=E+W)
Label(TITLE_FRAME, text= 'THIS IS THE TITLE PART', fg='sky blue', bg='black', font='none 40 bold',
borderwidth=5).grid(row=0,column=10)
#New Window Button
ENTRY_FRAME = Frame(window, bg='sky blue', relief = SUNKEN)
ENTRY_FRAME.grid(row=40, column=0, columnspan=20, padx=15, pady=15)
Label(ENTRY_FRAME, text= 'SELECT THE APPROPRIATE DETAILS:',
bg = 'sky blue', fg='black', font='none 10 bold', borderwidth=5).grid(row=0, column=0, columnspan=20)
NEW_WINDOW = Button(ENTRY_FRAME, text="NEW WINDOW", font='None 8 bold', width=30, command=New_page, fg= 'black', bg='white')
NEW_WINDOW.grid(row = 3, column = 0, columnspan = 3, padx = 10, pady = 10)
window.mainloop()
#Calling the Tkinter function
window()
Like in the comments, Toplevel is the way to go for this one. What I changed:
Moved making the window object globally
Renamed the function to make it makeWindow(master)
makeWindow(master) now takes in a master widget. This will make
all of the widgets made there be part of the master window.
New_page was modified to make a new Toplevel() widget
TITLE_FRAME is now made first and then grid is called on it
(EDIT) These edits fix the problems with the original window closing the program.
We want to remap the closing behaviour to act how we want. This is done with window.protocol("WM_DELETE_WINDOW",callback). We must define the callback function, in this case, deleteWindow(win).
What delete window does is take a window, and if it is the root window it hides it. Otherwise, it deletes the window. I used window.withdraw() in my code, but there's probably a better way to do it.
The way it knows if it should close the program is by keeping track of the number of active windows in the activeWindows variable. When a window is created, the number increases, when delete it decreases. If the number of active windows is 0, we can delete the main window to close the program cleanly.
The way we bind the deleteWindow(win) callback is through an anonymous function. Normally, the protocol mentioned above does not give any arguments, but we want to know which window called the function. To do this, whenever we bind the destruction of the window, we define a anonymous function using lambda that calls deleteWindow.
.
from tkinter import *
window = Tk()
window.resizable(0,0)
window.configure(background='grey')
window.state('zoomed')
window.geometry("2000x4000")
activeWindows = 1
def deleteWindow(win):
if win == window:
window.withdraw()
else:
win.destroy()
global activeWindows
activeWindows-=1
if activeWindows <= 0:
window.destroy()
#New Window
def New_page():
global activeWindows
activeWindows+=1
NEW_WINDOW=Toplevel(background='grey')
NEW_WINDOW.geometry("2000x4000")
NEW_WINDOW.protocol("WM_DELETE_WINDOW",lambda:deleteWindow(NEW_WINDOW))
makeWindow(NEW_WINDOW)
#Main Window
def makeWindow(master):
#Title Frame
TITLE_FRAME = Frame(master, relief = GROOVE, bg = "black", width=2000, height=160)
TITLE_FRAME.grid(row=0, column=0, columnspan = 150, rowspan = 30, sticky=E+W)
Label(TITLE_FRAME, text= 'THIS IS THE TITLE PART', fg='sky blue', bg='black', font='none 40 bold',
borderwidth=5).grid(row=0,column=10)
#New Window Button
ENTRY_FRAME = Frame(master, bg='sky blue', relief = SUNKEN)
ENTRY_FRAME.grid(row=40, column=0, columnspan=20, padx=15, pady=15)
Label(ENTRY_FRAME, text= 'SELECT THE APPROPRIATE DETAILS:',
bg = 'sky blue', fg='black', font='none 10 bold', borderwidth=5).grid(row=0, column=0, columnspan=20)
NEW_WINDOW = Button(ENTRY_FRAME, text="NEW WINDOW", font='None 8 bold', width=30, command=New_page, fg= 'black', bg='white')
NEW_WINDOW.grid(row = 3, column = 0, columnspan = 3, padx = 10, pady = 10)
window.protocol("WM_DELETE_WINDOW",lambda: deleteWindow(window))
#Calling the Tkinter function
makeWindow(window)
window.mainloop()

Categories