我已经将tkinter窗口划分为单元格(使用框架)。如何定义适用于每个单元的方法?

时间:2019-01-08 22:50:40

标签: python canvas tkinter

我无法获得一种创建的方法来应用于在tkinter中创建的所有帧。

使用Python 3.7。我使用Frame在tkinter中创建了一个简单的网格,并使用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 :(得分:1)

在lambda中,您引用的是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保留为对象属性确实没有意义,最好使用local变量,将解决方案更改为:

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()

还有更多的样式问题,但这似乎值得指出,因为它会导致您的问题并可能造成混乱。