Tkinter Image and text display - python

Im trying to use Tkinter to display an image and text like this
however I do not know how to do it, any help would be appreciated.
I tried writing some code of my own, however the most I got is text displaying UNDER the image, not next to it like shown

The anwser was in the explanation of grid geometry posted by figbeam.
The only thing I needed to do was add rowspan=2, columnspan=2
If someone wants to see the final code;
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
root.geometry("800x500")
img = ImageTk.PhotoImage(Image.open("img.png"))
panel = Label(root, image = img)
panel.grid(row=0,column=0, rowspan=2, columnspan=2)
text1 = "Hello World"
text2 = "Hello Again"
l1 = Label(root, text = text1).grid(row = 0, column = 2, sticky=S)
l2 = Label(root, text = text2).grid(row = 1, column = 2, sticky=N)
root.mainloop()

Related

Tkinter grid system weird placement of buttons

I am trying to create Hangman game in Tkinter. I am using buttons for choosing the letters, row for the grid is 0, and column is 0,1,2,3 up to 26. For down rows I have label, picture, etc. Now, there is space between first couple of buttons, and when picture is displayed, there is even more spaces, so they even can fit on the window. Here is example code and I will also attach picture from the original program. How can I fix the buttons? picture 1 picture 2
from tkinter import *
from PIL import ImageTk, Image
window = Tk()
A = Button(text ="A").grid(row = 0, column = 0)
B = Button(text ="B").grid(row = 0, column = 1)
C = Button(text ="C").grid(row = 0, column = 2)
D = Button(text ="D").grid(row = 0, column = 3)
E = Button(text ="E").grid(row = 0, column = 4)
lbl = Label(text = "Hello").grid(row = 1, column = 0)
photo = ImageTk.PhotoImage(file='hang1.jpg')
def show_image():
pic = Label(window, image=photo).grid(row=3, column=2)
btn = Button(window, text = "Show image", command = show_image).grid(row = 2, column = 2)
window.mainloop()
It is not weird but standard behavior in all tools which use grid - ie. in Excel or in <table> in HTML .
If you put bigger element in the same column then other elements in then same column will use more space.
One method is to use span which inform then element/image should use more columns and then it will may not resize column - but if image will be too big then it may resize even all columns.
In tkinter in grid() you can use column=0, columnspan=26 to use all columns for image. The same you can use for word and button and they will be centered.
import tkinter as tk # PEP8: `import *` is not preferrred
from PIL import ImageTk, Image
import string
# --- functions --- # PEP8: all functions at the beginning
def show_image():
pic['image'] = photo
# --- main ---
span = len(string.ascii_uppercase)
print('span:', span)
window = tk.Tk()
for number, char in enumerate(string.ascii_uppercase):
b = tk.Button(window, text=char) # use `window` as parent
b.grid(row=0, column=number)
lbl = tk.Label(window, text="Hello")
lbl.grid(row=1, column=0, columnspan=span)
pic = tk.Label(window) # create empty label and later replace only image in this label
pic.grid(row=2, column=0, columnspan=span)
photo = ImageTk.PhotoImage(file='lenna.png')
btn = tk.Button(window, text="Show image", command=show_image)
btn.grid(row=3, column=0, columnspan=24)
window.mainloop()
Result:
Other method is to use Frame to group buttons and then you can use different layout (grid, pack, place) to put other elements
In this version I use frame as parent for buttons.
I can also use different layout to put other elements - pack() - but I could use also grid() but it would be independent of the grid inside the frame.
import tkinter as tk # PEP8: `import *` is not preferrred
from PIL import ImageTk, Image
import string
# --- functions --- # PEP8: all functions at the beginning
def show_image():
pic['image'] = photo
# --- main ---
span = len(string.ascii_uppercase)
print('span:', span)
window = tk.Tk()
frame = tk.Frame(window)
frame.pack()
for number, char in enumerate(string.ascii_uppercase):
b = tk.Button(frame, text=char) # use `frame` as parent
b.grid(row=0, column=number)
lbl = tk.Label(window, text="Hello")
lbl.pack()
pic = tk.Label(window)
pic.pack()
photo = ImageTk.PhotoImage(file='lenna.png')
btn = tk.Button(window, text="Show image", command=show_image)
btn.pack()
window.mainloop()
BTW:
Image Lenna from Wikipedia
PEP 8 -- Style Guide for Python Code

Image viewer app: function to display next picture not working

I've been watching this youtube tutorial and had (I thought) a way better idea of solving the build an image viewer app.
But nothing happens on input, and I don't understand why, I think I might have totally misunderstood list as it doesn't start with the first picture (index 0).
The code is here
from tkinter import *
from PIL import ImageTk,Image
i = 0
root = Tk()
root.title("Learning to code")
root.iconbitmap('blue.PNG')
my_img1 = ImageTk.PhotoImage(Image.open("pics\me1.JFIF"))
my_img2 = ImageTk.PhotoImage(Image.open("pics\me2.JPG"))
my_img3 = ImageTk.PhotoImage(Image.open("pics\me3.JPG"))
my_img4 = ImageTk.PhotoImage(Image.open("pics\me4.JPG"))
my_img5 = ImageTk.PhotoImage(Image.open("pics\pop.JPG"))
img_list = [my_img1,my_img2,my_img3,my_img4,my_img5]
my_label = Label(image=img_list[i])
my_label.grid(row=0,column=0,columnspan=3)
def f_fwd():
global i
global my_label
if i < 4 :
my_label.grid_forget()
i =+1
my_label = Label(image=img_list[i])
my_label.grid(row=0,column=0,columnspan=3)
def f_bwd():
return
button_bwd = Button(root, text= "<<")
button_bwd.grid(row=1,column=0)
button_quit =Button(root, text="Exit", command= root.quit)
button_quit.grid(row=1,column=1)
button_fwd = Button(root, text=">>", command=f_fwd())
button_fwd.grid(row=1,column=2)
root.mainloop()
Sorry if I worded the problem poorly.
I expected the index to go up and display the next picture in the list when the f_fwd function is called from the button command, and I don't understand why its not working.

How to open a PIL image on every tkinter button press?

I am very new to Pyton and programming in general, and for my first project i am trying to make a script with Tkinter interface that should do the following:
Allow user to write some text into an entry,
on button click place that text on an image with a defined name,
save that image under the name that is current date and time,
repeat all of the above on button click.
The script works properly only once (after the first button click) then it places the entered text on previously entered text.
I gather that's because it opens the initial image only once and does other steps every time the button is clicked, but i can't seem to write the code that defines the initial image into command=lambda (it causes various errors).
Here is my code:
import tkinter as tk
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime
def adresat1_function(self): draw.text(xy=(273, 215), text=(entry_1.get()),
fill=(0, 0, 0), font=font_type)
root = tk.Tk()
root.title("Postal")
root.maxsize(height=530, width=590,)
canvas = tk.Canvas(root, height=530, width=590, highlightthickness=0)
canvas.pack()
frame_1 = tk.Frame(canvas, bg='#75a3a3', bd=2)
frame_1.place(x=5, y=10, height=200, width=580, anchor='nw')
entry_1 = tk.Entry(frame_1, font=18,)
entry_1.place(x=202, y=0, width=374, height=22,)
#Image
image = Image.open('Blank.jpg')
font_type = ImageFont.truetype('arial.ttf',14,)
draw = ImageDraw.Draw(image)
#Button
button = tk.Button(frame_1, text = 'Fill', width=8,
command=lambda:
#Fill
(adresat1_function(entry_1.get()),
image.save(datetime.now().strftime("%Y-%m-%d %H-%M-%S") + '.jpg'),))
button.place(x=202, y=160, width=374, height=22,)
root.mainloop()
What has to be done to make this program save the entered text on a new image without rewriting it on top of the previously entered text?
I may not even know some of the Python core concepts, in that case sorry for dumb question. Thanks in advance.
Modifying your code like below, will solve the problem. What you want is that every time that you press the button, a new image copy is created and you can apply your text there:
import tkinter as tk
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime
# Changes here.
def adresat1_function(self):
newImage = image.copy()
draw = ImageDraw.Draw(newImage)
draw.text(xy=(273, 215), text=(entry_1.get()),fill=(0, 0, 0), font=font_type)
newImage.save(datetime.now().strftime("%Y-%m-%d %H-%M-%S") + '.jpg')
root = tk.Tk()
root.title("Postal")
root.maxsize(height=530, width=590,)
canvas = tk.Canvas(root, height=530, width=590, highlightthickness=0)
canvas.pack()
frame_1 = tk.Frame(canvas, bg='#75a3a3', bd=2)
frame_1.place(x=5, y=10, height=200, width=580, anchor='nw')
entry_1 = tk.Entry(frame_1, font=18,)
entry_1.place(x=202, y=0, width=374, height=22,)
#Image
image = Image.open('Blank.jpg')
font_type = ImageFont.truetype('arial.ttf',14,)
newImage = None
#Button
button = tk.Button(frame_1, text = 'Fill', width=8,
command=lambda:
# Changes in fill.
(adresat1_function(entry_1.get()),))
button.place(x=202, y=160, width=374, height=22,)
root.mainloop()

Add an image on a 'price button' tkinter

A very simple question again. Once again, I have done my research on all websites but only one article kind of helps me.
Here is the article: How do I create a button in Python Tkinter to increase integer variable by 1 and display that variable?
And this is the code I am interested in (from the article above):
import tkinter
import sys
root = tkinter.Tk()
root.geometry("200x200")
root.title("His Button Increaser")
counter = tkinter.IntVar()
def onClick(event=None):
counter.set(counter.get() + 1)
tkinter.Label(root, textvariable=counter).pack()
tkinter.Button(root, text="Increase", command=onClick, fg="dark green", bg =
"white").pack()
root.mainloop()
Basically, I want to add an image to the button and remove the text on that button, so the user sees a picture, and when they click on the button, it displays the price at the top.
The part of my code I want to implement is:
PhotoImage(file = "imageofcar".png")
Thanks :)
To display an image on the button, you just have to pass the associated PhotoImage object to the Button through the parameter named image. Here is the solution:
import tkinter
root = tkinter.Tk()
root.geometry("200x200")
root.title("His Button Increaser")
counter = tkinter.IntVar()
def onClick(event=None):
counter.set(counter.get() + 1)
tkinter.Label(root, textvariable=counter).pack()
photo = tkinter.PhotoImage(file='imageofcar.png')
tkinter.Button(root, image=photo, command=onClick, fg="dark green", bg = "white").pack()
root.mainloop()
You can do this as following: First you create a PhotoImage object in which you pass the image you want to load as parameter, then you configure your button to accept this image at the specified size and finally you pack the button with pack():
from tkinter import *
import sys
root = Tk()
root.geometry("200x200")
root.title("His Button Increaser")
counter = IntVar()
def onClick(event=None):
counter.set(counter.get() + 1)
label = Label(root, textvariable=counter).pack()
button = Button(root, text="Increase", command=onClick, fg="dark green", bg = "white")
photo = PhotoImage(file = "imageofcar.png")
button.config(image=photo,width="100",height="100")
button.pack()
root.mainloop()
You can add an image to a button like this:
image = Image.open("imageofcar.jpg")
photo = ImageTk.PhotoImage(image)
b.config(image=photo)
where b is a reference to the button object.
It's usually a bad idea to create a Tk object and "pack" it in one line, because the pack function returns None.
These changes added to your code results in this:
import tkinter
import sys
from PIL import Image, ImageTk
root = tkinter.Tk()
root.geometry("200x200")
root.title("His Button Increaser")
counter = tkinter.IntVar()
def onClick(event=None):
counter.set(counter.get() + 1)
tkinter.Label(root, textvariable=counter).pack()
b = tkinter.Button(root, text="Increase", command=onClick, fg="dark green", bg =
"white")
b.pack()
image = Image.open("imageofcar.jpg")
photo = ImageTk.PhotoImage(image)
b.config(image=photo)
root.mainloop()

Image not displaying in Tkinter Label widget

I'm trying to get an image to display in a Tkinter Label widget. This code works inside a class in PyCharm, but doesn't get past the 'tk.Label' line in the main app. I've consulted other answers here but haven't been able to figure out why the image isn't displaying in the main app.
logo_filepath = "/Users/xxx/MASTER/pymol/Master/cache/logos/tmpbhWv2Ts.gif"
self.img = tk.PhotoImage(file = logo_filepath)
self.logo = tk.Label(self, image=self.img)
self.logo.photo = self.img
self.logo.grid(row=0, column=3, rowspan=10, columnspan=4)
It's a very simple error. Just make sure that you aren't defining self.[Your Variable] outside of a class. Because self is only available in classes. Also, Here's my code:
import Tkinter as tk
root = tk.Tk()
logo_filepath = "Your File Path..."
img = tk.PhotoImage(file = logo_filepath)
logo = tk.Label(root, image=img)
logo.photo = img
logo.grid(row=0, column=3, rowspan=10, columnspan=4)
tk.mainloop()

Categories