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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我已经将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()

我预计我将悬停的特定细胞变为红色。实际上只有右下角的单元格才有。

答案

在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)作为对象属性保留是没有意义的,你最好使用局部变量,将解决方案更改为:

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

有更多的风格问题,但这似乎值得指出,因为它导致了你的问题,可能会造成混乱。

以上是关于我已经将tkinter窗口划分为单元格(使用框架)。如何定义适用于每个单元格的方法?的主要内容,如果未能解决你的问题,请参考以下文章

用Python tkinter 做一个图形界面表格需要带框架线?

如何将列和行设置为 tkinter 框架中的窗口大小?

如何在 tkinter 中创建一个自调整大小的按钮网格?

在 TKinter 窗口中创建图形?

tkinter:在画布上使用滚动条

带有自定义单元格的 UITableView 弹出窗口失败,单元格属性始终为零