Python Forum

Full Version: Problem with tkinter widget list
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
This is part of the Enigma project that I am working on.
I'm adding a new post here, because this is a question having to do specifically with a GUI issue.
The program I am working on is PatchBoard.py to follow.
The images used (and expected in a sub directory named image)
can be downloaded here: https://github.com/Larz60p/Enigma/tree/master/src/image
or just clone the unfinished project with: git clone https://github.com/Larz60p/Enigma
PatchBoard.py:
import tkinter as tk
import tkinter.font as tkFont
import EnigmaPaths
import json


class PatchBoard:
    def __init__(self, parent):
        """
        Initialization
        :param parent: Containing tkinter widget
        """
        self.parent = parent
        self.patch_jacks = [ ]
        self.num_colors = 13
        self.patch_color_used = [0] * self.num_colors
        print(f'patch_color_used: {self.patch_color_used}')
        self.epath = EnigmaPaths.EnigmaPaths()

        with self.epath.enigma_info.open() as f:
            self.rotor_info = json.load(f)

        self.alpha = self.rotor_info['unencoded']

        with self.epath.color_info.open() as f:
            self.colors = json.load(f)

        self.parent.update()
        self.parent_width, self.parent_height = parent.winfo_width(), parent.winfo_height()
        print(f'width: {self.parent_width}, height: {self.parent_height}')

        # print(self.colors)
        self.bgcolor = self.colors['.w3-theme-d5']['background-color']

        self.patchbaord = tk.Frame(self.parent, relief=tk.RAISED, bg=self.bgcolor)
        self.patchbaord.grid(row=0, column=0, sticky='nsew')
        self.create_jacks()

    def create_jacks(self):
        self.patch_jacks = [ ]
        plug = self.epath.imagepath / 'plug1.png'
        self.customFont = tkFont.Font(family="Helvetica", size=10)
        self.img = tk.PhotoImage(file=plug)
        self.topframe = tk.Frame(self.patchbaord, relief=tk.RAISED, padx=2, pady=2, bg=self.bgcolor)
        self.middleframe = tk.Frame(self.patchbaord, relief=tk.RAISED, padx=2, pady=2, bg=self.bgcolor)
        self.bottomframe = tk.Frame(self.patchbaord, relief=tk.RAISED, padx=2, pady=2, bg=self.bgcolor)
        self.topframe.grid(row=0, column=0)
        self.middleframe.grid(row=1, column=0)
        self.bottomframe.grid(row=2, column=0)
        for n, i in enumerate('QWERTZUIO'):
            row = [ ]
            row.append(i)
            row.append('base') # slot for color
            row.append(tk.Label(self.topframe, bg='black', fg='white', text=i,
                                font=self.customFont).grid(row=0, column=n))
            row.append(tk.Button(self.topframe, bd=0, image=self.img,
                                 command=lambda jack=i: self.light_me_up(jack)).grid(row=1, column=n))
            self.patch_jacks.append(row)

        for n, i in enumerate('ASDFGHJK '):
            row = [ ]
            row.append(i)
            row.append('base') # slot for color
            if i == ' ':
                row.append(tk.Label(self.middleframe, bg='black', fg='white',
                                    text=i).grid(row=0, rowspan=2, column=n))
                row.append(None)
            else:
                row.append(tk.Label(self.middleframe, bg='black', fg='white', text=i,
                                    font=self.customFont).grid(row=0, column=n))
                row.append(tk.Button(self.middleframe, bd=0, image=self.img,
                                     command=lambda jack=i: self.light_me_up(jack)).grid(row=1, column=n))
            self.patch_jacks.append(row)

        for n, i in enumerate('PYXCVBNML'):
            row = [ ]
            row.append(i)
            row.append('base') # slot for color
            row.append(tk.Label(self.bottomframe, bg='black', fg='white', text=i,
                                font=self.customFont).grid(row=0, column=n))
            row.append(tk.Button(self.bottomframe, bd=0, image=self.img,
                                 command=lambda jack=i: self.light_me_up(jack)).grid(row=1, column=n))
            self.patch_jacks.append(row)
        for row in self.patch_jacks:
            print(f'row: {row}')

    def light_me_up(self, p_index):
        print(f'{p_index} Pushed')
        # Let there be light!
        subidx = [p_index in x for x in self.patch_jacks]
        n_index = [i for i, x in enumerate(subidx) if x is True][0]
        print(f'n_index: {n_index}')
        print(f'self.patch_jacks[n_index]: {self.patch_jacks[n_index]}')
        color_idx = self.patch_color_used.index(0)
        if self.patch_jacks[n_index][1] == 'base':
            try:
                print(f'color_idx: {color_idx}')
                t_image = self.epath.imagepath / f'color{color_idx+1}.png'
                newimg = tk.PhotoImage(file=t_image)
                self.patch_jacks[n_index][3].configure(image=newimg)
                self.patch_jacks[n_index][3].image = newimg
                self.patch_color_used[color_idx] = 1
            except:
                pass
        else:
            # toggle unlit
            self.patch_jacks[n_index][3].configure(image=self.img)
            self.patch_jacks[n_index][3].image = self.img
            self.patch_color_used[color_idx] = 0



if __name__ == '__main__':
    root = tk.Tk()
    root.title('Test window for patchboard')
    # root.geometry('600x400+10+10')
    app = PatchBoard(root)
    root.mainloop()
when I run this, I am printing out the values that I am storing in my button array,
but none are appending, each entry should have the format:
['letter value', color_index, tk.Label, tk.Button]
but what I get (partial list)is:
Output:
row: ['Q', 'base', None, None] row: ['W', 'base', None, None] row: ['E', 'base', None, None] row: ['R', 'base', None, None] row: ['T', 'base', None, None] row: ['Z', 'base', None, None] row: ['U', 'base', None, None] row: ['I', 'base', None, None] row: ['O', 'base', None, None] row: ['A', 'base', None, None]
I'm not sure why the widget entries are showing up as None.
So, why?
The method grid of a widget, returns None.
Instead of appending the object direct to the list, you should use following pattern:

for col, text in enumerate('PYXCVBNML'):
    label = tk.Label(self.bottomframe, bg='black', fg='white', text=text, font=self.customFont)
    button = tk.Button(self.bottomframe, bd=0, image=self.img, command=lambda jack=text: self.light_me_up(jack))
    label.grid(row=0, column=col)
    button.grid(row=1, column=col)
    self.patch_jacks.append([text, 'base', label, button])
I understood with your first sentence. Thanks!
I don't usually append grid to the definition, but did for whatever reason this time.
It was driving me nuts, because I have used arrays of this sort in the past without issue.