I am working on a tkinter GUI which utilises a canvas widget in order to have an image in the background, and widgets above.This GUI will run on a 320x240
raspberry pi screen.I am new to designing GUIs for these screens, having only developed for laptops in the past. Currently the GUI looks like this:
As you can see, it is far too small. What I want is:
Expected Outcome
The reason I have made the geometry 320x240
is because I want to run this GUI on my Raspberry Pi Screen which is 320x240
. The pi however mirrors the output of the HDMI cable to the screen. The HDMI outputs 1280x480
. I just need it too look sharp on the raspberry pi screen, it doesn't matter how stretched it looks on the HDMI output.
Code
#!/usr/bin/env python
try:
import Tkinter as tk
except:
import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
root.attributes('-fullscreen', True)
root.geometry("1280x480")
#Define Canvas
canvas = tk.Canvas(root, width=320, height=240)
canvas.grid(row=1,column=1)
# translates an rgb tuple of int to a tkinter friendly color code
def _from_rgb(rgb):
return "#%02x%02x%02x" % rgb
# Called when user presses View Log button
def viewLogRaise():
#Hide Previous Windows
canvas.itemconfigure(logButtonWindow, state="hidden")
canvas.itemconfigure(titleLabelWindow, state="hidden")
#Open Closed Windows
canvas.itemconfigure(backButtonWindow, state="normal")
canvas.itemconfigure(logTextWindow, state="normal")
quote = """HAMLET: To be, or not to be--that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune
Or to take arms against a sea of troubles
And by opposing end them. To die, to sleep--
No more--and by a sleep to say we end
The heartache, and the thousand natural shocks
That flesh is heir to. 'Tis a consummation
Devoutly to be wished."""
logText.insert(tk.END, quote)
def backToMenu():
#Hide Previous Windows
canvas.itemconfigure(backButtonWindow, state="hidden")
canvas.itemconfigure(logTextWindow, state="hidden")
#Open Closed Windows
canvas.itemconfigure(logButtonWindow, state="normal")
canvas.itemconfigure(titleLabelWindow, state="normal")
# Background
pathToGif = "redpoly2.jpg"
# red_background=Image.open("redBackground.gif")
backgroundImage = ImageTk.PhotoImage(file=pathToGif)
canvas.background = backgroundImage
bg = canvas.create_image(0, 0, anchor=tk.NW, image=backgroundImage)
titleLabel = tk.Label(root,fg="white", text="TEXT",borderwidth=2,relief="solid", bg=_from_rgb((239, 36, 37)), font=("Courier", 44))
titleLabelWindow = canvas.create_window(160,90,window=titleLabel)
logButton = tk.Button(root,fg="white",text="View Log",command=viewLogRaise,borderwidth=2,relief="raised",bg=_from_rgb((239, 36, 37)), font=("Courier", 22))
logButtonWindow = canvas.create_window(160,180,window=logButton)
backButton = tk.Button(root,fg="white",text="Back",command=backToMenu,borderwidth=2,relief="raised",bg=_from_rgb((239, 36, 37)))
backButtonWindow = canvas.create_window(20,227,window=backButton)
canvas.itemconfigure(backButtonWindow, state="hidden")
logText=tk.Text(root,bg="white",height=12,width=35,borderwidth=2,relief="solid")
logTextWindow = canvas.create_window(160,110,window=logText)
canvas.itemconfigure(logTextWindow, state="hidden")
root.mainloop()
What I tried
I used root.attributes('-fullscreen', True)
, thinking this would scale the contents of the root frame to match the screens resolution, however this line only makes the tkinter window full size.
I thought about resizing the whole GUI to run on 1280x480
however this would mean that their would be too many pixels for the pi screen to show.
redpoly2 image
You can have a background image without using a Canvas
widget and doing so will allow you to use tkinter's geometry managers to place your widgets. I don't really understand the relationship between the Raspberry Pi's 320x240 screen and the 1280x480 HDMI one.
The code below illustrates how to display a background image and some widgets on top of it. There's also a Button
to toggle the window's size between the two you want.
from PIL import Image, ImageTk
try:
import Tkinter as tk
except:
import tkinter as tk
path_to_bkgr_img = "redpoly2.jpg"
WIN_SIZES = (320, 240), (1280, 480)
# Translates an rgb tuple of int to a tkinter friendly color code.
def _from_rgb(rgb):
return "#%02x%02x%02x" % rgb
def change_size():
""" Sets/changes window size to next one available in WIN_SIZES. """
global cur_size
cur_size = (cur_size + 1) % len(WIN_SIZES)
config_window()
def config_window():
""" Sets root window's title, size, and background image. """
global background_label
geometry = '{}x{}'.format(*WIN_SIZES[cur_size])
root.geometry(geometry)
root.title(geometry)
# Resize background to fit window size.
btn_img = background_image.resize(WIN_SIZES[cur_size], resample=Image.BICUBIC)
btn_img = ImageTk.PhotoImage(btn_img) # Make tkinter compatible.
if not background_label: # Create Label if necessary.
background_label = tk.Label(root)
background_label.config(image=btn_img)
background_label.image = btn_img # Keep reference.
background_label.place(x=0, y=0, relwidth=1, relheight=1)
root = tk.Tk()
background_image = Image.open(path_to_bkgr_img)
background_label = None
cur_size = 0
config_window()
titleLabel = tk.Label(root, fg="white", text="TEXT", borderwidth=2, relief="solid",
bg=_from_rgb((239, 36, 37)), font=("Courier", 44))
titleLabel.pack(padx=5, pady=5, expand=1)
logButton = tk.Button(root, fg="white", text="Change Size", command=change_size,
borderwidth=2, relief="raised", bg=_from_rgb((239, 36, 37)),
font=("Courier", 22))
logButton.pack(padx=5, pady=5, expand=1)
root.bind_all('<KeyPress-Escape>', lambda *event: quit()) # Press Esc key to quit app.
root.mainloop()
Here are screenshots showing the what's displayed for each size: