Code:
import tkinter, urllib.request, json, io
from PIL import Image, ImageTk
main = tkinter.Tk()
main.geometry('500x500 800 300')
dogapi = urllib.request.urlopen(f'https://dog.ceo/api/breeds/image/random')
dogjson = dogapi.read()
dogdict = json.loads(dogjson)
url=dogdict['message']
m = urllib.request.urlopen(url)
mp = io.BytesIO(m.read())
mpi = Image.open(mp)
tkimg = ImageTk.PhotoImage(mpi)
l = tkinter.Label(main, image=tkimg)
b = tkinter.Button(main, text='Next Dog', command='do something to refresh the dog photo')
l.pack()
main.mainloop()
I have this code that gets a random dog photo and loads it in to a window, as well as a button. This works fine but the "Next Dog" button doesn't actually do anything, and the dog photo almost never matches up with the window. How could I add functionality to the button, and make the dog photo size consistent?
CodePudding user response:
You can put the fetching of the dog image in a function and update the image of the label inside the function. Then assign this function to the command
option of the button.
import tkinter, urllib.request, json, io
from PIL import Image, ImageTk
main = tkinter.Tk()
main.geometry('500x500 800 300')
# maximum size of image
W, H = 500, 460
# resize image but keeping the aspect ratio
def resize_image(img):
ratio = min(W/img.width, H/img.height)
return img.resize((int(img.width*ratio), int(img.height*ratio)), Image.ANTIALIAS)
def fetch_image():
dogapi = urllib.request.urlopen(f'https://dog.ceo/api/breeds/image/random')
dogjson = dogapi.read()
dogdict = json.loads(dogjson)
url = dogdict['message']
m = urllib.request.urlopen(url)
mpi = resize_image(Image.open(m))
tkimg = ImageTk.PhotoImage(mpi)
l.config(image=tkimg) # show the image
l.image = tkimg # save a reference of the image to avoid garbage collection
# label to show the image
l = tkinter.Label(main, image=tkinter.PhotoImage(), width=W, height=H)
b = tkinter.Button(main, text='Next Dog', command=fetch_image)
l.pack()
b.pack()
fetch_image() # fetch first image
main.mainloop()