How can I put image on Button in python tkinter? - python

This is my code in Tkinter. I tried to show buttons with the image when I select the grid size in tkinter UI. My problem is that when I go to put an image inside a button, it does not display it. List grid2 already have images with using the shuffle method.
Any help is appreciated.
import tkinter
import tkinter.ttk
import random
def startButton():
global my_list, roundNum, tmp_list, startTime
grid_size = combobox1.get()[0]
roundNum = combobox2.get()[0]
gridActorList(my_list)
imageUpdate()
startTime=time.time()
def imageUpdate():
global grid_size
t = []
if grid_size == 2:
photo_1 = tkinter.PhotoImage(file="picture/"+grid2[0]+".png")
photo_2 = tkinter.PhotoImage(file="picture/"+grid2[1]+".png")
photo_3 = tkinter.PhotoImage(file="picture/"+grid2[2]+".png")
photo_4 = tkinter.PhotoImage(file="picture/"+grid2[3]+".png")
for k in range(1,5):
t.append(tkinter.Button(window, image=photo_+str(k)))
for i in range(0,4):
t[i].pack()
window = tkinter.Tk()
window.title('Finding different picture!')
window.geometry('500x400')
#combobox
values1=[str(i)+"x"+str(i) for i in range(2,6)] #grid size
values2=[str(j)+"times" for j in range(1,10,2)] #play time size
combobox1=tkinter.ttk.Combobox(window, height=5, width=15, values=values1,
justify='center', takefocus=True )
combobox2=tkinter.ttk.Combobox(window, height=5, width=15, values=values2,
justify='center', takefocus=True )
combobox1.set("select size")
combobox2.set("select times")
combobox1.place(x=15, y=15)
combobox2.place(x=155, y=15)
#startButton
startBtn = tkinter.Button(window, text='start', command=startButton)
startBtn.place(x=300, y=15)
#variables
my_list = []
roundNnum = 0
window.mainloop()
I've tried to minimize the code. If there are more codes required, I'll edit it.

Your code does not run. This makes it hard to debug. But I can see that you're not saving references to the images you put in the buttons.
As the images are created inside a function they will be garbage collected when the function exits. Fix this by saving a reference to the image with the button widget. Examine the example below:
import tkinter as tk
def create_button():
photo = tk.PhotoImage(file="images/gilliam.png")
image_button = tk.Button(window, image=photo)
image_button.image = photo # Save a reference to the image
image_button.pack()
window = tk.Tk()
create_button()
window.mainloop()

Related

python issue adds a new label

take a look at this code
well it happens to just add another label for no reason
import tkinter
from tkinter import *
clicks = 1
def click_count():
global clicks
# making the label that shows how many idk you have
label = Label(frame, text="you have " + str(clicks), font=(('Courrier'), 32))
label.pack()
clicks += 1
label.pack()
#generating the window
root = tkinter.Tk()
root.geometry('500x500')
#making the expandable frame
frame = Frame(root)
frame.pack(expand=YES)
#making the button
button = Button(frame, text= "click", font=(('Courrier'), 32), command=click_count)
button.pack()
root.mainloop()
and then i tried this
and i also tried to remove the label.pack at the end
but it still does the same thing which is adding another label
import tkinter
from tkinter import *
clicks = 1
def click_count():
global clicks
# making the label that shows how many idk you have
label = Label(frame, text="you have " + str(clicks), font=(('Courrier'), 32))
label.pack()
label.destroy()
clicks += 1
label.pack()
#generating the window
root = tkinter.Tk()
root.geometry('500x500')
#making the expandable frame
frame = Frame(root)
frame.pack(expand=YES)
#making the button
button = Button(frame, text= "click", font=(('Courrier'), 32), command=click_count)
button.pack()
root.mainloop()
i was expecting it to add a nmber to the label but it just shows another label
It does not add a Label for no reason. It adds the label because that's what your function tells it to do. Each time you click the button, the function is executed that creates and packs a new Label.
What you should do is create the label at the onset and link it to a variable. Then, you can change the value of this variable in the function.
Also, you don't have to import tkinter twice and it's sensible to update the clicker first and then display the result instead of showing the last value it had. Your approach works in such a small program but the value of clicks will always be one higher than displayed. So, you may get into problems when you use the value.
from tkinter import *
def click_count():
global clicks
clicks += 1
click_counter.set("you have " + str(clicks))
#Initiate root
root = Tk()
root.geometry('500x500')
#Set initial values for click counter
clicks = 0
click_counter = StringVar()
click_counter.set("you have 0")
#making the expandable frame
frame = Frame(root)
frame.pack(expand=YES)
# making the label that shows how many idk you have
label = Label(frame, textvariable=click_counter, font=(('Courrier'), 32)) ## The label gets updated, whenever the value of click_counter changes.
label.pack()
#making the button
button = Button(frame, text= "click", font=(('Courrier'), 32), command=click_count)
button.pack()
root.mainloop()

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.

Tkinter label does not change images dynamically

I want to change the image of the one labels in time with 2 other images but it immideatly skipts to the last one. Any suggestions?
I have tried using time.sleep incase it might happen so fast that before i could notice but it didnt work.
import tkinter
from tkinter import *
from PIL import Image , ImageTk
import time
window = tkinter.Tk()
window.geometry("500x500")
window.title("Pomodoro Timer")
window.image_1 = ImageTk.PhotoImage(Image.open("1.jpg"))
window.image_2 = ImageTk.PhotoImage(Image.open("2.jpg"))
window.image_3 = ImageTk.PhotoImage(Image.open("3.jpg"))
lbl_1 = tkinter.Label(window, image=window.image_1)
lbl_1.place(x=150,y=100)
lbl_2 = tkinter.Label(window, image=window.image_2)
lbl_2.place(x=200,y=100)
def display_numbers():
lbl_1
lbl_2
display_numbers()
def clicked():
i=1
while i<3:
if i==1:
lbl_1.configure(image=window.image_2)
time.sleep(0.91)
i += 1
elif i==2:
lbl_1.configure(image=window.image_3)
time.sleep(0.91)
i += 1
btn = tkinter.Button(window, text="Start", command=clicked)
btn.place(x=200,y=450,width=100)
window.mainloop()

Looping through images in tkinter

I have a small tkinter GUI, which just contains an image of a thermostat. I have an image for each temperature to make a little animation of the temperature increasing. I have got this working to the point where it loops through all the images succesfully, however after the last image is displayed it just disappears. Here is my code so far
#!/usr/bin/python3
import tkinter as tk
from PIL import ImageTk, Image
import time
root = tk.Tk()
root.geometry("1280x720")
root.configure(background='white')
def loopTemp(maxTemp):
for x in range(0, maxTemp + 1):
if x < 22:
thermostat = ImageTk.PhotoImage(Image.open("thermo_"+str(x)+".png"))
panel.configure(image = thermostat)
panel.configure(text = str(x))
root.update_idletasks()
time.sleep(0.07)
light = ImageTk.PhotoImage(Image.open("light-on.png"))
thermostat = ImageTk.PhotoImage(Image.open("thermo_0.png"))
B = tk.Button(root, text ="Start", command= lambda: loopTemp(21))
panel = tk.Label(root, image = thermostat, text="0", compound=tk.CENTER, font=("Helvetica", 60), fg="white")
panel.configure(background='white')
B.pack()
panel.pack(side=tk.LEFT, fill = "both", expand = "yes")
root.mainloop()
Replace:
...
thermostat = ImageTk.PhotoImage(...)
panel.configure(image = thermostat)
...
with:
...
panel.img = ImageTk.PhotoImage(...)
panel.configure(image = panel.img)
...
In order to keep the reference of the image object wherever panel exists, thus have a consistent image display like suggested in the comment here.

Switching images based on arduino input in a python 2.7 generated Tkinter window won't show the images

I wrote an Arduino code which reacts to buttons and physical interactions and then send the results to the computer on which my python program (2.7) is running.
The python code has two functions:
Create a new text file named after the unixtimestamp and fill it
with all the data it receives.
Look through the data it receives for the code phrases "a1" and "b1"
and then show the corresponding image.
When the Arduino starts it will send the "a1" as a first value to fill the window. After that, it should switch based on the data it sends.
This is my current code:
from Tkinter import *
from random import *
import serial
import time
root = Tk()
prompt = StringVar()
root.title("vision")
label = Label(root, fg="dark green")
label.pack()
frame = Frame(root,background='red')
frame.pack()
canvas = Canvas(height=200,width=200)
canvas.pack()
timestamp = int(time.time())
filename=str(timestamp)+".txt"
f = open(str(filename),"w")
f.write("\n")
f.write(str(filename))
f.write("\n")
arduino = serial.Serial('COM5', 115200, timeout=.1)
while True:
data = arduino.readline()[:-2] #the last bit gets rid of the new-line chars
print data
f.write(str(data))
f.write("\n")
#Invoking through button
TextWindow = Label(frame,anchor = NW, justify = LEFT, bg= 'white', fg = 'blue', textvariable = prompt, width = 75, height=20)
TextWindow.pack(side = TOP)
if data == "a1":
canvas.delete("all")
image1 = PhotoImage(file = "c2.gif")
canvas.create_image(0,0,anchor='nw',image=image1)
canvas.image = image1
if data == "b1":
canvas.delete("all")
image1 = PhotoImage(file = "c2.gif")
canvas.create_image(0,0,anchor='nw',image=image1)
canvas.image = image1
root.mainloop()
It generates the window but it is empty.
I can not seem to find where my error is.
Additionaly:
I used an other tutorial wich gave me he basic code for the gui and images. In this there are two buttons wich switch the images which works.
from Tkinter import *
from random import *
pathy = randint(1, 2)
root = Tk()
prompt = StringVar()
root.title("vision")
label = Label(root, fg="dark green")
label.pack()
frame = Frame(root,background='red')
frame.pack()
canvas = Canvas(height=200,width=200)
canvas.pack()
def Image1():
canvas.delete("all")
image1 = PhotoImage(file = "c2.gif")
canvas.create_image(0,0,anchor='nw',image=image1)
canvas.image = image1
def Image2():
canvas.delete("all")
image1 = PhotoImage(file = "c1.gif")
canvas.create_image(0,0,anchor='nw',image=image1)
canvas.image = image1
TextWindow = Label(frame,anchor = NW, justify = LEFT, bg= 'white', fg = 'blue', textvariable = prompt, width = 75, height=20)
TextWindow.pack(side = TOP)
conversationbutton = Button(frame, text='right button',width=25,fg="green",command = Image1)
conversationbutton.pack(side = RIGHT)
stopbutton = Button(frame, text='left button',width=25,fg="red",command = Image2)
stopbutton.pack(side = RIGHT)
root.mainloop()
Once the mainloop() function has been called you have to use callbacks in order to run your own code. The Tkinter after() method can be used to run a section of code after a set amount of time.
In your case your code would look something like:
def update():
#your code here
root.after(1000, update)
update()
root.mainloop()
Calling root.after() inside of the update functions allows the function to keep running until the window is closed.
The after method as described at effbot gives the arguments as:
root.after(milliseconds, callback)
In your case you might have to call your processing code more often then every second.

Categories