Python Forum
[Tkinter] making a list of labels callable
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] making a list of labels callable
#1
Hi,

I'm trying to define 5 labels as a list of labels. The reason I want to do this is that later I can iterate through the labels with a for loop in order to make updates.

This is the code that works:

from tkinter import *
from PIL import Image, ImageTk

root = Tk()
root.title('some text')
root.geometry('1200x800')
root.configure(background='green')

def resize_cards(card):
    our_card_img = Image.open(card) # open the image
    our_card_resized_image = our_card_img.resize((150, 218)) # resize the image
    global our_card_image
    our_card_image = ImageTk.PhotoImage(our_card_resized_image) # output the card
    return our_card_image # return the card



backImage = resize_cards(f'images/pokerCards/backOfCard/back1.png')

cardLabel1 = Label(root, image=backImage, bg='snow')
cardLabel1.grid(sticky = W, row=0, column=0, pady=20, padx=20)

cardLabel2 = Label(root, image=backImage, bg='snow')
cardLabel2.grid(sticky = W, row=0, column=1, pady=20, padx=20)

cardLabel3 = Label(root, image=backImage, bg='snow')
cardLabel3.grid(sticky = W, row=0, column=2, pady=20, padx=20)

cardLabel4 = Label(root, image=backImage, bg='snow')
cardLabel4.grid(sticky = W, row=0, column=3, pady=20, padx=20)

cardLabel5 = Label(root, image=backImage, bg='snow')
cardLabel5.grid(sticky = W, row=0, column=4, pady=20, padx=20)




root.mainloop()
this code does not work:

from tkinter import *
from PIL import Image, ImageTk

root = Tk()
root.title('some text')
root.geometry('1200x800')
root.configure(background='green')
global cardLabel
#cardLabel = []

def resize_cards(card):
    our_card_img = Image.open(card) # open the image
    our_card_resized_image = our_card_img.resize((150, 218)) # resize the image
    global our_card_image
    our_card_image = ImageTk.PhotoImage(our_card_resized_image) # output the card
    return our_card_image # return the card



for f in range(5):
    global cardLabel, backImage
    cardLabel = []
    backImage = resize_cards(f'images/pokerCards/backOfCard/back1.png')
    cardLabel[f] = Label(root, image=backImage, bg='snow')
    cardLabel[f].grid(sticky = W, row=0, column=f, pady=20, padx=20)

root.mainloop()
It returns the following error:

Error:
cardLabel[f] = Label(root, image=backImage, bg='snow') IndexError: list assignment index out of range
Thanks
Reply
#2
Not sure why you are using globals but, give this a try.
You need to append to thr cardlabel list.

import tkinter as tk


def card_back(number):
    img = tk.PhotoImage(file='some.png')
    img.image = img
    labels = []
    for i in range(number):
        label = tk.Label(root)
        labels.append(label)
        labels[i]['image'] = img
        labels[i].grid(column=i, row=1, sticky='new', pady=20, padx=20)

root = tk.Tk()
card_back(5)
root.mainloop()

Another example

import tkinter as tk
from PIL import Image, ImageTk


def card_back(number):
    img = Image.open('cardback.png')
    img_resized = img.resize((140, 200))
    img = ImageTk.PhotoImage(img_resized)
    img.image = img
    labels = []
    for i in range(number):
        label = tk.Label(root, bg='darkgreen')
        labels.append(label)
        labels[i]['image'] = img
        labels[i].grid(column=i, row=1, sticky='new', pady=20, padx=20)

root = tk.Tk()
root['bg'] = 'darkgreen'
card_back(5)
root.mainloop()
laur3333 likes this post
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#3
Thanks a lot. It works with append.

* globals were a part of code I forgot to delete
Reply
#4
You created a list with no elements. Then you tried to set the value of elements in the list. That is why you got an index error.

Will the labels always display the same image, or will different labels display different images? If the later, your scheme of using the global variable backimage will not work. Each image needs a reference. If you have 5 cards with different images you cannot save them all in one variable (unless it is a list).

In this example I save a reference to the image in a dictionary. I am assuming that I will have multiple card images that will be reused (card back and 52 face images). If I want to flip a card over to show the face (Ace clubs) I would set the card image to "...ace_clubs.png".
import tkinter as tk
from PIL import Image, ImageTk

DEFAULT_IMAGE = f"images/pokerCards/backOfCard/back1.png"

class MainWindow(tk.Tk):
    def __init__(
        self,
        num_cards,
        *,
        title="Cards!!!",
        card_image=DEFAULT_IMAGE,
        background="green",
    ):
        self.card_images = {}
        super().__init__()
        self.title(title)
        self.configure(background=background)
        self.cards = [tk.Label(self, bg="snow") for _ in range(num_cards)]
        for col, card in enumerate(self.cards):
            self.set_card_image(card, card_image)
            card.grid(sticky=tk.W, row=0, column=col, pady=20, padx=20)

    def set_card_image(self, card, image_file):
        if image_file in self.card_images:
            image = self.card_images[image]
        else:
            image = ImageTk.PhotoImage(Image.open(image_file).resize((150, 218)))
            self.card_images[image_file] = image
        card["image"] = image

MainWindow(5).mainloop()
laur3333 likes this post
Reply
#5
Yes, that's correct, I will use multiple images. Thanks a lot for the explanations and for the example. They are really useful.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020