Python Tkinter Canvas 没有出现
Python Tkinter Canvas does not appear
你好,我在 python 上使用 Tkinter 包时遇到问题。我想创建一个包含两个主要小部件的 window,其中一个是 canvas,稍后将显示带有单元格的网格。在初始化 canvas 时,我使用 "create_rectangle" 来填充 canvas 所需的对象。此外,当单击一个单元格时(出于测试原因),canvas 应该改变其在矩形区域中的颜色。但是,当最初显示 window 时,一开始看不到任何对象(预期结果只会是白色矩形),只有当单击 canvas 时,该区域才会根据需要更改颜色。
在浏览互联网时,我尝试了 pack()- 和 create_rectangle()- 方法顺序的几种变体。这是代码:
from tkinter import *
from tkinter.ttk import *
import cells
GRID_WIDTH = 15
GRID_HEIGHT = 15
class Ui(Frame):
""" Class to represent the ui of conways game of life"""
def __init__(self, parent, grid):
self.parent = parent
self.grid = grid
Frame.__init__(self, parent)
self.__setup()
def __setup(self):
""" Method to setup the components of the ui """
self.parent.title("Conway's game of life")
self.pack()
#Setup a frame to hold control components
frame_cntrl = Frame(self)
frame_cntrl.pack(side = RIGHT, anchor="n")
self.__setup_cntrl_components(frame_cntrl)
#Setup a frame to hold the Grid
self.canvas = Canvas(self)
self.canvas.pack(side = LEFT)
self.__draw_grid()
self.canvas.bind("<Button-1>", self.__canvas_clicked)
def __setup_cntrl_components(self, parent):
""" Method to setup the control elements of the ui"""
#Setup a label for the generation
self.lb_generation = Label(parent, text="dummy")
self.lb_generation.pack(side = TOP)
#Setup a button for iteration
self.bt_iteration = Button(parent, text="Iterate")
self.bt_iteration.pack(side = TOP)
def __draw_cell(self, x, y):
""" Draws a cell on the canvas"""
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
color = "black" if self.grid.cell_alive(x, y) else "white"
x0 = width * x / self.grid.width + 1
x1 = width * (x + 1) / self.grid.width
y0 = height * y / self.grid.height + 1
y1 = height * (y + 1) / self.grid.height
self.canvas.create_rectangle(x0, y0, x1, y1, width=0, fill=color)
def __draw_grid(self):
""" Method to setup the grid itself"""
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
for i in range(0, self.grid.width):
for j in range(0, self.grid.height):
self.__draw_cell(i, j)
def __canvas_clicked(self, event):
""" Method for when the cell was clicked """
x, y, width, height = event.x, event.y, self.canvas.winfo_width(), self.canvas.winfo_height()
cell_x = int(x / width * self.grid.width)
cell_y = int(y / height * self.grid.height)
self.grid.switch_cell(cell_x, cell_y)
self.__draw_cell(cell_x, cell_y)
if __name__ == "__main__":
Ui(Tk(), cells.Grid(GRID_WIDTH, GRID_HEIGHT)).mainloop()
问题 1:
你的主要问题是,在 canvas 实际显示之前,canvas.winfo_width()
和 canvas.winfo_height()
没有 return canvas 的宽度和高度,但是值 1
.
我建议您创建 canvas 如下:
# Define canvas and save dimensions
self.canvas_width = 300
self.canvas_height = 200
self.canvas = Canvas(self, width = self.canvas_width,
height = self.canvas_height)
然后,在您的代码中,替换每个实例:
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
和
width, height = self.canvas_width, self.canvas_height
问题二:
创建每个单元格时,我认为您不需要在 x0
和 y0
上加 1。相反,它应该是:
x0 = width * x / self.grid.width
x1 = width * (x + 1) / self.grid.width
y0 = height * y / self.grid.height
y1 = height * (y + 1) / self.grid.height
你好,我在 python 上使用 Tkinter 包时遇到问题。我想创建一个包含两个主要小部件的 window,其中一个是 canvas,稍后将显示带有单元格的网格。在初始化 canvas 时,我使用 "create_rectangle" 来填充 canvas 所需的对象。此外,当单击一个单元格时(出于测试原因),canvas 应该改变其在矩形区域中的颜色。但是,当最初显示 window 时,一开始看不到任何对象(预期结果只会是白色矩形),只有当单击 canvas 时,该区域才会根据需要更改颜色。 在浏览互联网时,我尝试了 pack()- 和 create_rectangle()- 方法顺序的几种变体。这是代码:
from tkinter import *
from tkinter.ttk import *
import cells
GRID_WIDTH = 15
GRID_HEIGHT = 15
class Ui(Frame):
""" Class to represent the ui of conways game of life"""
def __init__(self, parent, grid):
self.parent = parent
self.grid = grid
Frame.__init__(self, parent)
self.__setup()
def __setup(self):
""" Method to setup the components of the ui """
self.parent.title("Conway's game of life")
self.pack()
#Setup a frame to hold control components
frame_cntrl = Frame(self)
frame_cntrl.pack(side = RIGHT, anchor="n")
self.__setup_cntrl_components(frame_cntrl)
#Setup a frame to hold the Grid
self.canvas = Canvas(self)
self.canvas.pack(side = LEFT)
self.__draw_grid()
self.canvas.bind("<Button-1>", self.__canvas_clicked)
def __setup_cntrl_components(self, parent):
""" Method to setup the control elements of the ui"""
#Setup a label for the generation
self.lb_generation = Label(parent, text="dummy")
self.lb_generation.pack(side = TOP)
#Setup a button for iteration
self.bt_iteration = Button(parent, text="Iterate")
self.bt_iteration.pack(side = TOP)
def __draw_cell(self, x, y):
""" Draws a cell on the canvas"""
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
color = "black" if self.grid.cell_alive(x, y) else "white"
x0 = width * x / self.grid.width + 1
x1 = width * (x + 1) / self.grid.width
y0 = height * y / self.grid.height + 1
y1 = height * (y + 1) / self.grid.height
self.canvas.create_rectangle(x0, y0, x1, y1, width=0, fill=color)
def __draw_grid(self):
""" Method to setup the grid itself"""
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
for i in range(0, self.grid.width):
for j in range(0, self.grid.height):
self.__draw_cell(i, j)
def __canvas_clicked(self, event):
""" Method for when the cell was clicked """
x, y, width, height = event.x, event.y, self.canvas.winfo_width(), self.canvas.winfo_height()
cell_x = int(x / width * self.grid.width)
cell_y = int(y / height * self.grid.height)
self.grid.switch_cell(cell_x, cell_y)
self.__draw_cell(cell_x, cell_y)
if __name__ == "__main__":
Ui(Tk(), cells.Grid(GRID_WIDTH, GRID_HEIGHT)).mainloop()
问题 1:
你的主要问题是,在 canvas 实际显示之前,canvas.winfo_width()
和 canvas.winfo_height()
没有 return canvas 的宽度和高度,但是值 1
.
我建议您创建 canvas 如下:
# Define canvas and save dimensions
self.canvas_width = 300
self.canvas_height = 200
self.canvas = Canvas(self, width = self.canvas_width,
height = self.canvas_height)
然后,在您的代码中,替换每个实例:
width, height = self.canvas.winfo_width(), self.canvas.winfo_height()
和
width, height = self.canvas_width, self.canvas_height
问题二:
创建每个单元格时,我认为您不需要在 x0
和 y0
上加 1。相反,它应该是:
x0 = width * x / self.grid.width
x1 = width * (x + 1) / self.grid.width
y0 = height * y / self.grid.height
y1 = height * (y + 1) / self.grid.height