How do I keep this image in the center of the window? - python

I'm making a hangman-like game; for that, I need all the different stages of the man to be visualized, hence images. I want the entire tkinter window to be an image, when I change the size it pushes the image right.
from tkinter import *
root=Tk()
root.geometry("600x350")
canvas = Canvas(root, width=1600, height=900)
canvas.pack()
img = PhotoImage(file="4.png")
canvas.create_image(470,190, image=img, )
root.mainloop()

If canvas is bigger than window then when you resize then it show more canvas but and it can looks like it moves image.
But if you use smaller canvas then pack() will try to keep centered horizontally. And if you add pack(expand=True) then it will try to keep it centered vertically.
In example code I added red background to window to show where is canvas
import tkinter as tk # PEP8: import *
root = tk.Tk()
root.geometry("600x350")
root['bg'] = 'red'
img = tk.PhotoImage(file="lenna.png")
canvas = tk.Canvas(root, width=600, height=350)
canvas.pack(expand=True)
canvas.create_image(300, 175, image=img)
root.mainloop()
Image Lenna from Wikipedia
PEP 8 -- Style Guide for Python Code
Before resizing:
After resizing:
If you want to draw only image then you could use Label(image=img)
import tkinter as tk # PEP8: import *
root = tk.Tk()
root.geometry("600x350")
root['bg'] = 'red'
img = tk.PhotoImage(file="lenna.png")
label = tk.Label(root, image=img)
label.pack(expand=True)
root.mainloop()
Before resizing:
After resizing:
BTW:
tkinter can bind() some function to event <Configure> and it will execute this function everytime when you resize window (and/or move window) - and this function may also move or resize image in window.
import tkinter as tk # PEP8: import *
from PIL import Image, ImageTk
def resize(event):
global img
lower = min(event.width, event.height)
#print(event.width, event.height, 'lower:', lower)
new_image = original_image.resize((lower, lower))
img = ImageTk.PhotoImage(new_image) # need to assign to global variable because there is bug in PhotoImage
label['image'] = img
# --- main ---
root = tk.Tk()
root.geometry("350x350")
root['bg'] = 'red'
original_image = Image.open("lenna.png")
img = ImageTk.PhotoImage(original_image)
label = tk.Label(root, image=img)
label.pack(expand=True)
root.bind('<Configure>', resize)
root.mainloop()
Before (it resized image at start to fit window):
After (it resized image to fit window):

Related

How to center an image in tkinter with PIL

I want to center an image in tkinter canvas. The only thing I could think of is using anchor = 'c' but that does not seem to work. I have also tried using it on the stage.
def newsetup(filelocation):
global width, height
for widgets in root.winfo_children():
widgets.destroy()
stage = Canvas(root, width = 1000, height = 700, highlightbackground = 'red', highlightthickness = 2)
stage.pack()
imgtk = ImageTk.PhotoImage(Image.open(filelocation))
stage.create_image(stage.winfo_width() + 2, stage.winfo_height() + 2, image = imgtk, anchor = CENTER)
stage.image = imgtk
if you want to center on canvas then you need
stage.winfo_width()/2, stage.winfo_height()/2
(even without anchor= which as default has value center)
But if you put image before it runs mainloop() then stage.winfo_width() stage.winfo_height() gives 0,0 instead of expected width, height (because mainloop creates window and it sets all sizes for widgets) and it may need root.update() to run mainloop once and it will calculate all sizes.
import tkinter as tk
from PIL import ImageTk, Image
root = tk.Tk()
stage = tk.Canvas(root, width=1000, height=700)
stage.pack()
root.update() # force `mainloop()` to calculate current `width`, `height` for canvas
# and later `stage.winfo_width()` `stage.winfo_height()` will get correct values instead `0`
#imgtk = ImageTk.PhotoImage(Image.open('lenna.png'))
imgtk = ImageTk.PhotoImage(file='lenna.png')
stage.create_image((stage.winfo_width()/2, stage.winfo_height()/2), image=imgtk, anchor='center')
stage.image = imgtk
root.mainloop()
Result:
Image Lenna from Wikipedia.
EDIT:
If you want to keep it centered when you resize window then you can bind event <Configure> to canvas and it will execute assigned function - and it can move image.
But it needs image ID which you can get when you create image
img_id = stage.create_image(...)
Because <Configure> is executed when it creates window so code doesn't need root.update() because on_resize() will set correct position at start.
import tkinter as tk
from PIL import ImageTk, Image
# --- functions ---
def on_resize(event):
# it respects anchor
x = event.width/2
y = event.height/2
stage.coords(img_id, x, y)
# it DOESN'T respects anchor so you have to add offset
#x = (event.width - imgtk.width())/2
#y = (event.height - imgtk.height())/2
#stage.moveto(img_id, x, y) # doesn't respect anchor
#stage.itemconfigure(img_id, ...)
# --- main ---
root = tk.Tk()
stage = tk.Canvas(root, width=1000, height=700)
stage.pack(fill='both', expand=True)
#root.update() # force `mainloop()` to calculate current `width`, `height` for canvas
# and later `stage.winfo_width()` `stage.winfo_height()` will get correct values instead `0`
#imgtk = ImageTk.PhotoImage(Image.open('lenna.png'))
imgtk = ImageTk.PhotoImage(file='lenna.png')
img_id = stage.create_image((stage.winfo_width()/2, stage.winfo_height()/2), image=imgtk, anchor='center')
stage.image = imgtk
stage.bind('<Configure>', on_resize) # run function when Canvas change size
root.mainloop()

Tkinter - rotate image with slider simultaneously

UPDATED -
New to tkinter
Is it possible to rotate a picture by using a slider simultaneously.
I have an image of a rotatory dial, beneath this image is a slider listed from 0 to 360. I would like the image to rotate clockwise as the slider is moved from 0 to 360, and anticlockwise as the slider is returned from 360 to 0.
ROTATION OF IMAGE WITH SLIDER WORKS CORRECTLY
I have ran into a bug, the image is black. Perhaps the image is too zoomed in? Apologies, I am new to python and tkinter.
Here is how the GUI should look Correct GUI
THIS IS HOW THE GUI LOOKS NOW Incorrect GUI with Slider
THIS IS HOW THE GUI LOOKS REMOVING THUMBNAIL LINE THUMBNAIL
Here is the updated code
# import necessary modules
from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
root = Tk()
root.title("Gesture Detection Application")
root.geometry("400x320") # set starting size of window
root.maxsize(400, 320) # width x height
root.config(bg="#6FAFE7") # set background color of root window
Heading = Label(root, text="Demonstrator Application2", bg="#2176C1", fg='white', relief=RAISED)
Heading.pack(ipady=5, fill='x')
Heading.config(font=("Font", 20)) # change font and size of label
image = Image.open("rotate_dial.png")
width, height = image.size
image.thumbnail((width/5, height/5))
photoimage = ImageTk.PhotoImage(image)
image_label = Label(root, image=photoimage, bg="white", relief=SUNKEN)
image_label.image = photoimage
image_label.pack(pady=5)
def rotate_image(degrees):
new_image = image.rotate(-int(degrees))
photoimage = ImageTk.PhotoImage(new_image)
image_label.image = photoimage #Prevent garbage collection
image_label.config(image = photoimage)
w2 = Scale(root, from_=0, to=360, tickinterval= 30, orient=HORIZONTAL, length=300, command = rotate_image)
w2.pack()
w2.set(0)
root.mainloop()
You can rotate the image using PIL (which you've already imported). You can link it to the Scale by adding a command.
image = Image.open("rotate_dial.png")
width, height = image.size
image.thumbnail((width/5, height/5))
photoimage = ImageTk.PhotoImage(image)
image_label = Label(root, image=photoimage, bg="white", relief=SUNKEN)
image_label.pack(pady=5)
def rotate_image(degrees):
new_image = image.rotate(-int(degrees))
photoimage = ImageTk.PhotoImage(new_image)
image_label.image = photoimage #Prevent garbage collection
image_label.config(image = photoimage)
w2 = Scale(root, from_=0, to=360, tickinterval= 30, orient=HORIZONTAL, length=300, command = rotate_image)
Instead of creating a PhotoImage initially, it now creates a PIL Image object. It then uses the height and width and the thumbnail function to replace the subsample. Then it uses ImageTk to turn it into a tkinter PhotoImage which is shown in the label. The Scale now has a command, rotate_image, which recieves the scale value, which is the number of degrees, and then uses PIL to create a new rotated image, which is then turned into a PhotoImage and displayed in the label by changing it's image with .config. Now when you move the slider, the image rotates with it.

How to make background Transparent in TKinter by converting Label widget into Canvas widget?

I have a code that is working perfectly but it's not giving me transparent background, (here is the image ) after a research on web, I found the solution by using canvas widget, we can us images with transparent background.
Here is my code,
import tkinter as tk
from PIL import Image, ImageTk
def work(progress=1):
if progress > 300: # define the width by yourself
return
tmp_images = ImageTk.PhotoImage(progress_images.resize((progress, 10))) # the image size
lb.image = tmp_images # keep reference
lb["image"] = tmp_images # change the image
root.add = root.after(100, work, progress+10) # define the amplitude by yourself
root = tk.Tk()
progress_images = Image.open("path.png")
lb = tk.Label(root, bg="black")
lb.pack(side="left")
work()
root.mainloop()
but I am confused how to change Label widget into Canvas ? can anyone help me please ? I am noob in Tkinter still!!!
You can use canvas.create_text(...) to replace the labels and then use canvas.itemconfig(...) to update the labels. I got this from an other stack over flow question
reference link :-
add label ..
Below is a modified code using Canvas:
import tkinter as tk
from PIL import Image, ImageTk
def work(progress=10):
if progress > 300: # define the width by yourself
return
canvas.image = ImageTk.PhotoImage(progress_images.resize((progress, 30))) # the image size
canvas.itemconfig(pbar, image=canvas.image) # update image item
root.add = root.after(100, work, progress+10) # define the amplitude by yourself
root = tk.Tk()
progress_images = Image.open("path.png")
canvas = tk.Canvas(root, width=300, height=30, bg='black', highlightthickness=0)
canvas.pack()
pbar = canvas.create_image(0, 0, anchor='nw') # create an image item
work()
root.mainloop()

tkinter - rectangle hidden under background image

I am trying to create a really simple HMI, to display different images and name of the file and other information in a lower bar using tkinter. I have created a layout, added the background image but the lower rectangle is not visible.
The background image overlays the rectangle, how can I force the ground image to behind all the other components inside the canvas? The black rectangle should be visible at the lower section of the picture
from PIL import Image, ImageTk
from tkinter import Tk, BOTH, Canvas
from tkinter.ttk import Frame, Label, Style
root = Tk()
root.title('Screen')
w = Canvas(root, width=800 , height=480)
w.pack()
back_ground = ImageTk.PhotoImage(Image.open("./icon/sync_background.bmp"))
back_ground_label = Label(image=back_ground, borderwidth=0)
back_ground_label.place(x=0,y=0)
w.create_rectangle(0, 400, 800, 480,outline="#000", fill="#000")
w.pack()
root.mainloop()
Your background image is placed on top of the canvas and so it hides the canvas. You should create the image using w.create_image(...) instead:
from PIL import Image, ImageTk
from tkinter import Tk, BOTH, Canvas
root = Tk()
root.title('Screen')
back_ground = ImageTk.PhotoImage(Image.open("./icon/sync_background.bmp"))
w = Canvas(root, width=800 , height=480)
w.pack()
w.create_image(0, 0, image=back_ground, anchor='nw')
w.create_rectangle(0, 400, 800, 480,outline="#000", fill="#000")
root.mainloop()
Here is what you can do:
from PIL import Image, ImageTk
from tkinter import Tk, BOTH, Canvas
from tkinter.ttk import Frame, Label, Style
root = Tk()
root.title('Screen')
w = Canvas(root, width=800 , height=480)
w.pack()
back_ground = ImageTk.PhotoImage(Image.open("./icon/sync_background.bmp"))
back_ground_label = Label(image=back_ground, borderwidth=0)
back_ground_label.place(x=0,y=0)
rect = w.create_rectangle(0, 400, 800, 480,outline="#000", fill="#000")
w.tag_raise(rect)
w.pack()
root.mainloop()
What this does is creates an object "rect" and then uses the tag_raise method on it to bring it in front.
Hope it helps!
Cheers!

tkinter window and background image don't align properly

I am writing a Simpsons trivia game as my first big programming project. My question is twofold:
Is this the right way to go about creating a background image? Keep in mind that my plan is to include the Simpsons theme song playing in the background as well as one or two buttons on top of the background image.
Assuming the code below is the right approach given what I want to accomplish, why am I getting a thin gray line on the left of my image and window? Ie. Why is the image not filling up the window perfectly like it is on the right side?
Here is my code:
from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
root = Tk()
root.title("The Simpsons Trivia Game")
root.geometry('400x600')
root.resizable(0,0)
def resize_image(event):
new_width = event.width
new_height = event.height
image = copy_of_image.resize((new_width, new_height))
photo = ImageTk.PhotoImage(image)
label.config(image = photo)
label.image = photo
image = Image.open('E:\Simpsons Trivia Game\SimpsonsPic.png')
copy_of_image = image.copy()
photo = ImageTk.PhotoImage(image)
label = ttk.Label(root, image = photo)
label.bind('<Configure>', resize_image)
label.pack(fill=BOTH, expand = YES)
root.mainloop()
tkinter window with background image (left side of window not perfectly alligned with background image
I'm not sure I understand everything, but I managed to get rid of the border (at least on Linux) by doing:
from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
root = Tk()
root.title("The Simpsons Trivia Game")
root.geometry("400x600")
root.resizable(0,0)
image = Image.open('/tmp/foobar.png')
photo = ImageTk.PhotoImage(image)
label = ttk.Label(root, image = photo)
label.pack()
label.place(relx=0.5, rely=0.5, anchor="center")
root.mainloop()

Categories