Я разделил окно tkinter на ячейки (используя рамку). Как определить метод, который будет применяться к каждой ячейке? - PullRequest
0 голосов
/ 09 января 2019

Я не могу получить метод, который я создал, чтобы применить ко всем кадрам, которые я создал в tkinter.

Работа на Python 3.7. Я создал простую сетку в tkinter с использованием Frame и покрасил каждую ячейку с помощью Canvas. Теперь я хочу использовать метод, который позволит мне выделять ячейку при наведении курсора на нее, но когда я это делаю, это относится только к самой последней ячейке.

import tkinter as tk

BOARD_DIM = 7
CELL_DIM = 50
CELL_BORDER = 1

# Creating reference spots for the grid
x_coord = list(range(BOARD_DIM))
y_coord = list(range(BOARD_DIM))
grid_coord = []
for x in x_coord:
    for y in y_coord:
        grid_coord.append((x, y))

class Credence():
    """
    Class for the tkinter window
    """
    def __init__(self, window):
        self._window = window

        self._window.geometry(str(BOARD_DIM*CELL_DIM)+'x'+
                              str(BOARD_DIM*CELL_DIM))

        for loc in grid_coord:
            # Dividing the window into cells
            self._cell = tk.Frame(self._window, width=CELL_DIM, 
                                  height=CELL_DIM,
                                  highlightthickness=CELL_BORDER,
                                  name='(' + str(loc[0]) + ',' + 
                                  str(loc[1]) + ')')
            self._cell.place(x=loc[0] * CELL_DIM, y=loc[1] * CELL_DIM)
            self._picasso = tk.Canvas(self._cell, bg='Yellow')
            # Highlight a cell in red when hovering over it
            self._picasso.bind('<Enter>',
                               lambda event: self._picasso.config(bg = 
                               'Red'))
            self._picasso.bind('<Leave>',
                               lambda event: self._picasso.config(bg = 
                               'Yellow'))
            self._picasso.pack()
            # Drawing a circle in every cell
            self._circle = self._picasso.create_oval(CELL_BORDER+1,
                                                 CELL_BORDER+1,
                                                 CELL_DIM-(CELL_BORDER*2),
                                                 CELL_DIM-(CELL_BORDER*2))

window = tk.Tk()
Credence(window)
window.mainloop()

Я ожидал, что конкретная ячейка, над которой я наведусь, изменит цвет на красный. В действительности только нижняя правая ячейка делает.

1 Ответ

0 голосов
/ 09 января 2019

Внутри лямбды вы ссылаетесь на self._picasso, но вы перезаписываете это на каждой итерации цикла, и оно не ссылается на холст, сгенерировавший событие.

Итак, вам нужно изменить:

        self._picasso.bind('<Enter>',
                           lambda event: self._picasso.config(bg = 
                           'Red'))
        self._picasso.bind('<Leave>',
                           lambda event: self._picasso.config(bg = 
                           'Yellow'))

Кому:

        self._picasso.bind('<Enter>',
                           lambda event: event.widget.config(bg = 
                           'Red'))
        self._picasso.bind('<Leave>',
                           lambda event: event.widget.config(bg = 
                           'Yellow'))

Кроме того, на самом деле нет смысла хранить последний _picasso (или _circle или _cell в этом отношении) как атрибут объекта, лучше использовать локальную переменную, изменив решение на :

import tkinter as tk

BOARD_DIM = 7
CELL_DIM = 50
CELL_BORDER = 1

# Creating reference spots for the grid
x_coord = list(range(BOARD_DIM))
y_coord = list(range(BOARD_DIM))
grid_coord = []
for x in x_coord:
    for y in y_coord:
        grid_coord.append((x, y))

class Credence():
    """
    Class for the tkinter window
    """
    def __init__(self, window):
        self._window = window

        self._window.geometry(str(BOARD_DIM*CELL_DIM)+'x'+
                              str(BOARD_DIM*CELL_DIM))

        for loc in grid_coord:
            # Dividing the window into cells
            _cell = tk.Frame(self._window, width=CELL_DIM,
                                  height=CELL_DIM,
                                  highlightthickness=CELL_BORDER,
                                  name='(' + str(loc[0]) + ',' +
                                  str(loc[1]) + ')')
            _cell.place(x=loc[0] * CELL_DIM, y=loc[1] * CELL_DIM)
            _picasso = tk.Canvas(_cell, bg='Yellow')
            # Highlight a cell in red when hovering over it
            _picasso.bind('<Enter>',
                               lambda event: event.widget.config(bg =
                               'Red'))
            _picasso.bind('<Leave>',
                               lambda event: event.widget.config(bg =
                               'Yellow'))
            _picasso.pack()
            # Drawing a circle in every cell
            _circle = _picasso.create_oval(CELL_BORDER+1,
                                           CELL_BORDER+1,
                                           CELL_DIM-(CELL_BORDER*2),
                                           CELL_DIM-(CELL_BORDER*2))

window = tk.Tk()
Credence(window)
window.mainloop()

Есть и другие проблемы со стилем, но, похоже, на это стоит обратить внимание, так как это усугубило вашу проблему и, возможно, замешательство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...