issue using Singleton pattern with tkinter Photoimage/Tk in python
<p>Wrote the following code to display a chessboard using Tkinter in Python:</p>

<pre><code>import tkinter as tk

class Gui(tk.Tk):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls, *args, **kwargs)
            cls._instance.__initialized = False
        return cls._instance

def __init__(self):
    if self.__initialized:
        return
    self.__initialized = True
    super().__init__()

class Color(object):
    white =(0xff,0xff,0xff)
    black =(0x00,0x00,0x00)

class Tile(tk.PhotoImage):
    @staticmethod
    def putTile(image, color, width, height, coordinates):
        pix = "#%02x%02x%02x" % color
        coor = (coordinates[0]*width, coordinates[1]*height)
        line = "{" + " ".join([pix]*width) + "}"
        image.put(" ".join([line]*height),coor)

class Grid(tk.PhotoImage):
    def __init__(self,grid):
        super().__init__(width=10*len(grid), height=10*len(grid[0]))
        for x in range(len(grid)):
            for y in range(len(grid[x])):
                Tile.putTile(self,Color.white if grid[x][y]==1 else
                             Color.black,10,10,(x,y))

class ChessBoard(Grid):
    chessboard = 4 * ([4 * [0,1]] + [4 * [1,0]])
    def __init__(self):
        super().__init__(self.chessboard)
</code></pre>

<p>So <code>Gui()</code> is implemented as a singleton pattern. Also <code>tk.Tk.__init__()</code> is made to be called only once, otherwice I got a window everytime <code>Gui()</code> was called.</p>

<p>I would expect the following to display a window with a chessboard:<br>
<b>Case 1:</b></p>

<pre><code>label = tk.Label(Gui(), image=ChessBoard())
label.pack()
Gui().mainloop()
</code></pre>

<p>This creates an empty window without errors or warnings. A print statement shows that method <code>tilePut</code> is indeed called.</p>

<p>Only when I add an additional <code>Gui()</code> statement in my program, as shown below, everyting works perfectly and a chessboard is printed.</p>

<p><b>Case 2:</b></p>

<pre><code>Gui()
label = tk.Label(Gui(), image=ChessBoard())
label.pack()
Gui().mainloop()
</code></pre>

<p>So I guess the <code>image.put</code> call requires a <code>Gui()</code> to exist. Though if I try the following code:</p>

<p><b>Case 3:</b></p>

<pre><code>board = ChessBoard()
label = tk.Label(Gui(), image=board)
label.pack()
Gui().mainloop()
</code></pre>

<p>I get an error about calling <code>image.put</code> too soon. Considering I do not get this same error in case 1, I am surprised case 1 does not work. Can anyone explain why?</p>

<p>The answer to your questions boils down to two factors:</p>

<ol>
<li>The root window must exist before you can create an image</li>
<li>You must keep a reference to the image or tkinter will destroy 
the image data when it does garbage collection.</li>
</ol>

<p>The proper way to use this code would be to first create an instance of <code>Gui</code>, then create <code>Chessboard</code> and save what is returned in a variable. You can then use these references in the rest of your code.</p>

<p>This is the common way to accomplish that:</p>

<pre><code>root = Gui()
chessboard = ChessBoard()
label = tk.Label(root, image=chessboard)
label.pack()
root.mainloop()
</code></pre>

<p>Since you are defining <code>Gui</code> as a singleton, the following will also work. However, I think the use of a singleton adds complexity and makes the code less clear since it looks like you are creating three instances of <code>Gui</code>:</p>

<pre><code>Gui()
chessboard = ChessBoard()
label = tk.Label(Gui(), image=chessboard)
label.pack()
Gui().mainloop()
</code></pre>

python tkinter singleton