Search code examples
pythontkinterreinforcement-learningtkinter-canvas

How to display tkinter-canvas for Reinforcement Learning environment


I'm creating a custom Reinforcement Learning environment. So far, the environment is simply a 3 x 3 grid. I would like to create a custom environment which is why I do not work with OpenAI Gym. The ultimate objective is that a DQN- agent finds a suitable path to maximize the possible rewards and reaches a destination on the grid (Let's say, e.g., goal is to get to field with coordinates [2|2]).

I have created a sample class for the environment (class Env). The "architecture" of the grid is described in the function build_canvas(self). As visible, I used tkinter.canvas for defining the grid system. Unfortunately, when I try to instantiate an object of type Env, the grid is not displayed.

    class Env(tk.Tk):

        def __init__(self):
            super(Env, self).__init__()
            print("This is the standard constructor of our 
                   environment class.")
            self.build_canvas()

        def build_canvas(self):
            canvas = tk.Canvas(self, bg='green', height=HEIGHT, 
            width=WIDTH)

           ## Create grid with 3x3 (3 rows with 3 columns)
            for c in range(0, WIDTH, 60):
                 x1, y1, x2, y2 = c, 0, c, HEIGHT
                 canvas.create_line(x1, y1, x2, y2)
            for r in range(0, HEIGHT, 60):
                 x1, y1, x2, y2 = 0, r, HEIGHT, r
                 canvas.create_line(x1, y1, x2, y2)

            canvas.pack()
            return canvas


        def render(self):
            print("This renders the environment to the screen.")

        def reset(self):
            print("This resets the environment.")

       def step(self, action):
            print("This takes an action and the environment.")


   if __name__ == "__main__":
           env = Env()

It just prints out the strings to the console, however, the grid is not loaded at all. Does anyone have suggestions?


Solution

  • 1- you need to call mainloop() on your root (here env).
    2- you must keep a reference of the canvas (self.canvas)
    3- In python 3, you can call super like this: super().__init__(), without arguments.
    4- There were some confusions between WIDTH and HEIGHT in the loop drawing the lines.

    import tkinter as tk
    
    
    HEIGHT, WIDTH = 500, 500
    
    
    class Env(tk.Tk):
    
        def __init__(self):
            super().__init__()
            print("This is the standard constructor of ourenvironment class.")
            self.canvas = self.build_canvas()
            self.canvas.pack()
    
        def build_canvas(self):
            canvas = tk.Canvas(self, bg='green', height=HEIGHT, width=WIDTH)
    
           ## Create grid with 3x3 (3 rows with 3 columns)
            for c in range(0, WIDTH, 60):
                x1, y1, x2, y2 = c, 0, c, HEIGHT
                canvas.create_line(x1, y1, x2, y2)
            for r in range(0, HEIGHT, 60):
                x1, y1, x2, y2 = 0, r, WIDTH, r
                canvas.create_line(x1, y1, x2, y2)
    
            return canvas
    
    
        def render(self):
            print("This renders the environment to the screen.")
    
        def reset(self):
            print("This resets the environment.")
    
        def step(self, action):
             print("This takes an action and the environment.")
    
    
    if __name__ == "__main__":
        env = Env()
        env.mainloop()