0

I am trying to produce a star algorithm using Tkinter 2d graphical user interface. I have modified the following code having found it originally on here:

from tkinter import *

class CellGrid(Canvas):
    def __init__(self,master, rowNumber, columnNumber, cellSize, theMap):
        Canvas.__init__(self, master, width = cellSize * columnNumber , height = cellSize * rowNumber)

        self.cellSize = cellSize

        self.grid = []
        for row in range(rowNumber):
            line = []
            for column in range(columnNumber):
                line.append(Cell(self, column, row, cellSize, theMap[row][column]))
            self.grid.append(line)

        print (self.grid[0][0].value)
        self.draw()

    def draw(self):
        for row in self.grid:
            for cell in row:
                cell.draw()

class Cell():
    colors = {
            0: 'white',    # untried
            1: 'black',    # obstacle
            2: 'green',    # start
            3: 'red',      # finish
            4: 'blue',     # open
            5: 'gray',     # closed
            6: 'orange',   # path
         }

    def __init__(self, master, x, y, size, value):
        self.master = master
        self.abs = x
        self.ord = y
        self.size= size
        self.fill = "white"
        self.value = value


    def setValue(self, value):
        self.value = value

    def draw(self):
         if self.master != None :
            if self.value == 0:
                self.fill = self.white
            elif self.value == 1:
                self.fill = self.black
            elif self.value == 2:
                self.fill = self.green
            elif self.value == 3:
                self.fill = self.red
            elif self.value == 4:
                self.fill = self.blue
            elif self.value == 5:
                self.fill = self.gray
            elif self.value == 6:
                self.fill = self.orange

            xmin = self.abs * self.size
            xmax = xmin + self.size
            ymin = self.ord * self.size
            ymax = ymin + self.size

            self.master.create_rectangle(xmin, ymin, xmax, ymax, fill = self.fill, outline = "black")

def main():
    Map = [
            [2, 0, 0, 0, 0],
            [0, 1, 1, 1, 1],
            [0, 1, 3, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 0, 0, 0, 0],
          ]
    root = Tk()
    c = tk.Canvas(root, height=1000, width=1000, bg='white')
    my_gui = CellGrid(root, len(Map), len(Map[0]), 40, Map)


    root.mainloop()

But when I go to run it, nothing displays.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
J. Allan
  • 3
  • 1
  • 3
    Are you sure you run anything at all? Python is not C, function named `main()` is not special and will not be run automatically. You should call it explicitly. (See here: http://stackoverflow.com/questions/22492162/understanding-the-main-method-of-python#22493194) – avysk Feb 24 '17 at 19:56
  • Your title asks why the canvas _is_ showing. Are you asking why it's showing, or why it is _not_ showing? If the latter, you should say so in the title. – Bryan Oakley Feb 25 '17 at 16:12

1 Answers1

1

A lot of small and not-small misunderstandings are blocking the display of the star algorithm.

Problem 1 - incomplete calling main() function.

As @avysk suggests as comment, the first blocking point is due to the missing of main() preamble in Python.

Just add the following code after the def main() function:

if __name__ == '__main__':
    main()

Problem 2 - typo and missing pack() to the main Canvas display.

Because the tk symbol is not defined, the main Canvas shall be declared as follow:

c = Canvas(root, height=1000, width=1000, bg='white')

Instead of:

c = tk.Canvas(root, height=1000, width=1000, bg='white')

And after the magic missing call is pack():

c.pack() # magic call to display the (1000 x 1000) white canvas

Problem 3 - missing call to the secondary Canvas display.

As for the main Canvas, it was missing the call of pack(), two possibilities could be used to display the secondary Canvas.

  1. Add my_gui.pack() to fit the main Canvas to the size of the secondary Canvas,
  2. Or my preferred solution, add my_gui.place(relx=0.5, rely=0.5, anchor=CENTER) to center the secondary Canvas to the main Canvas.

To display the secondary Canvas:

my_gui = CellGrid(c, len(Map), len(Map[0]), 40, Map)
my_gui.place(relx=0.5, rely=0.5, anchor=CENTER)

Problem 4 - misunderstanding of dictionary use in the Cell::draw() function.

The displayed error is "AttributeError: 'Cell' object has no attribute 'green'".

The value of the first cell self.grid[0][0].value = 2 and when drawing the cell, the following self.fill = self.green generates the error.

Three possibilities could be used to solve that error:

  1. Replace the self.fill = self.<color> (7 cases) by self.fill = '<color>',
  2. Use the declared dictionary colors and replace the 7 cases by a unique call.

The use of dictionary could be (sol 2):

if 0 <= self.value <= 6: # check if value in range of colors
    self.fill = Cell.colors[self.value]

Instead of the long if-elif (sol 1):

    if self.value == 0:
        self.fill = 'white' # Error: self.white
    elif self.value == 1:
        self.fill = 'black' # Error: self.black
    elif self.value == 2:
        self.fill = 'green' # Error: self.green
    elif self.value == 3:
        self.fill = 'red' # Error: self.red
    elif self.value == 4:
        self.fill = 'blue' # Error: self.blue
    elif self.value == 5:
        self.fill = 'gray' # Error: self.gray
    elif self.value == 6:
        self.fill = 'orange' # Error: self.orange
J. Piquard
  • 1,665
  • 2
  • 12
  • 17