1

I am doing a school project, to make a game using tkinter. I am trying to display and image by using an image link stored in a text file, however it will only display the image if there is an error at the end of the def subroutine that stops the program. I am having trouble understanding why it will show the image if there is an error stoping the program but will display everything else but the image if there is no error(by error i mean some random letters in the code)

Am I missing something?

Note: the game involves picking which country a flag belongs to.

import tkinter as tk  
from PIL import ImageTk,Image
import random
import time


main_window = tk.Tk()
main_window.title("Fun With Flags")
...... #removed the unnecessary part

def play():
   #opens the question text file
   question_file = open('Flags.txt')
   lines = question_file.readlines()
   image_link = lines[1]

   #removes the \n from the end of the variable
   size = len(image_link)
   flag_link = image_link[:size - 1]
   print(flag_link)

   #Finds the image dimensions
   flag = Image.open(flag_link)
   width = flag. size[0]
   height = flag. size[1]
   print(width)
   print(height)

   #Resizes the image
   new_height = 200
   new_width  = int(new_height * width / height)
   flag = flag.resize((new_width, new_height), Image.ANTIALIAS)

   #Displays the flag
   flag = ImageTk.PhotoImage(flag) 
   c.create_image(450, 300, image = flag, anchor = "s")

homepage()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685

1 Answers1

0

You need to keep reference to the image, or the image gets swept by pythons garbage collector.

So you need something like c.image = flag after flag = flag.resize((new_width, new_height), Image.ANTIALIAS)

This is the full code:

import tkinter as tk  
from PIL import ImageTk,Image
import random
import time


main_window = tk.Tk()
main_window.title("Fun With Flags")

c = tk.Canvas(main_window, height = 600, width = 900, bg = "black")
c.pack(side = 'top', fill = 'both', expand = 'yes')

def homepage():

   c.delete("all")

   #Play Button
   c.create_rectangle (350,250, 550, 350, fill = "green", outline = "black", width = 5)
   c.create_text(450, 300, text = "Play", font = "Times 30 bold", fill = "black")

   #Info Button
   c.create_rectangle (350,450, 550, 550, fill = "green", outline = "black", width = 5)
   c.create_text(450, 500, text = "More Information", font = "Times 20 bold", fill ="black")

   def click(event):

    #play button
    if event.x > 350 and event.x < 550 and event.y > 250 and event.y < 350:
        
        #creates the background    
        c.create_rectangle (0, 0, 900, 600, fill = "black")
        c.create_rectangle(200, 375, 400, 450, fill = "green", outline = "red", width = 5)
        c.create_rectangle(500, 375, 700, 450, fill = "green", outline = "red", width = 5)
        c.create_rectangle(200, 475, 400, 550, fill = "green", outline = "red", width = 5)
        c.create_rectangle(500, 475, 700, 550, fill = "green", outline = "red", width = 5)

        play()

    #info button
    elif event.x > 350 and event.x < 550 and event.y > 450 and event.y < 550:
        print("info")
        info()

  c.bind("<Button-1>", click)


def play():

   #opens the question text file
   question_file = open('Flags.txt')
   lines = question_file.readlines()
   image_link = lines[1]

   #removes the \n from the end of the variable
   size = len(image_link)
   flag_link = image_link[:size - 1]
   print(flag_link)

   #Finds the image dimensions
   flag = Image.open(flag_link)
   width = flag. size[0]
   height = flag. size[1]
   print(width)
   print(height)

   #Resizes the image
   new_height = 200
   new_width  = int(new_height * width / height)
   flag = flag.resize((new_width, new_height), Image.ANTIALIAS)

   #Displays the flag
   flag = ImageTk.PhotoImage(flag) 
   c.image = flag #This is the line I added
   c.create_image(450, 300, image = flag, anchor = "s")

def info():
   .....
homepage()
Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46
coderoftheday
  • 1,987
  • 4
  • 7
  • 21
  • 1
    Is it actually necessary to include the entire code in the answer? I think the changes were only made to the function, so just include the function part. It helps keep the answer minimal and understandable also more readable – Delrius Euphoria Sep 23 '20 at 18:01
  • i stated what code needed to be added initially, i then showed how it works in a full working code in case they struggle to implement my answer. – coderoftheday Sep 23 '20 at 18:03
  • 1
    Yes its fine, but it might give an impression that the solution is "hard". Keep it minimal right? If OP dont understand, they can ask. This more disastrous that that. – Delrius Euphoria Sep 23 '20 at 18:05
  • Thank you so so much, this is perfect :) – Aden Cassaidy Sep 24 '20 at 05:03