Python Tkinter画布不显示

Python Tkinter画布不显示,python,tkinter,tkinter-canvas,Python,Tkinter,Tkinter Canvas,您好,我在python上使用Tkinter包时遇到问题。我想创建一个包含两个主要小部件的窗口,其中一个是画布,稍后将显示带有单元格的网格。初始化画布时,我使用“create_rectangle”用所需的对象填充画布。此外,当单击单元格时(出于测试原因),画布应更改矩形区域的颜色。但是,当最初显示窗口时,看不到任何对象(预期结果仅为白色矩形),并且仅当在画布上单击时,该区域才会根据需要更改其颜色。 在浏览互联网时,我尝试了几种不同的pack()和create_rectangle()方法。代码如下:

您好,我在python上使用Tkinter包时遇到问题。我想创建一个包含两个主要小部件的窗口,其中一个是画布,稍后将显示带有单元格的网格。初始化画布时,我使用“create_rectangle”用所需的对象填充画布。此外,当单击单元格时(出于测试原因),画布应更改矩形区域的颜色。但是,当最初显示窗口时,看不到任何对象(预期结果仅为白色矩形),并且仅当在画布上单击时,该区域才会根据需要更改其颜色。 在浏览互联网时,我尝试了几种不同的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()
从tkinter导入*
从tkinter.ttk导入*
输入单元格
网格宽度=15
网格高度=15
类用户界面(框架):
“”“表示康威生活游戏ui的类”“”
定义初始化(自、父、网格):
self.parent=parent
self.grid=grid
帧。\uuuu初始化(自,父)
self.\u设置()
def___设置(自):
“”“用于设置ui组件的方法”“”
self.parent.title(“康威的人生游戏”)
self.pack()
#设置一个框架以容纳控制组件
帧\u cntrl=帧(自身)
框架组件(侧=右侧,锚定=“n”)
自安装组件(框架组件)
#设置一个框架以固定网格
self.canvas=画布(self)
self.canvas.pack(侧=左)
自绘制网格()
self.canvas.bind(“,self.\u canvas\u单击)
定义设置控制组件(自身、父级):
“”“用于设置ui控件元素的方法”“”
#为生成设置标签
self.lb_generation=标签(父项,text=“dummy”)
self.lb_generation.pack(侧面=顶部)
#为迭代设置一个按钮
self.bt_iteration=按钮(父级,text=“Iterate”)
self.bt_iteration.pack(side=TOP)
定义绘制单元(自身、x、y):
“”“在画布上绘制单元格”“”
宽度,高度=self.canvas.winfo_width(),self.canvas.winfo_height()
color=“黑色”如果self.grid.cell\u处于活动状态(x,y),则为“白色”
x0=宽度*x/self.grid.width+1
x1=宽度*(x+1)/self.grid.width
y0=高度*y/自网格高度+1
y1=高度*(y+1)/self.grid.height
self.canvas.create_矩形(x0,y0,x1,y1,宽度=0,填充=color)
定义绘制网格(自):
“”“设置网格本身的方法”“”
宽度,高度=self.canvas.winfo_width(),self.canvas.winfo_height()
对于范围内的i(0,self.grid.width):
对于范围内的j(0,自网格高度):
自绘制单元(i,j)
已单击定义画布(自身、事件):
“”“单击单元格时的方法”“”
x、 y,width,height=event.x,event.y,self.canvas.winfo_width(),self.canvas.winfo_height()
单元格x=int(x/width*self.grid.width)
单元y=int(y/高度*自网格高度)
self.grid.switch\u单元(单元x、单元y)
自绘制单元(单元x、单元y)
如果名称=“\uuuuu main\uuuuuuuu”:
Ui(Tk(),cells.Grid(Grid\u WIDTH,Grid\u HEIGHT)).mainloop()

问题1

您的主要问题是,在实际显示画布之前,
canvas.winfo_width()
canvas.winfo_height()
不返回画布的宽度和高度,而是返回值
1

我建议您按如下方式创建画布:

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

问题2:

创建每个单元格时,我认为不需要在
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

问题1

您的主要问题是,在实际显示画布之前,
canvas.winfo_width()
canvas.winfo_height()
不返回画布的宽度和高度,而是返回值
1

我建议您按如下方式创建画布:

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

问题2:

创建每个单元格时,我认为不需要在
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

FWIW
winfo_width()
winfo_height()
仅在画布实际显示在屏幕上之前返回1。一旦显示,它将返回实际值。在此之前,tkinter无法确定尺寸,因为它取决于包装/放置/网格选项。谢谢@Bryan,我更新了答案以澄清这一点!FWIW
winfo_width()
winfo_height()
仅在画布实际显示在屏幕上之前返回1。一旦显示,它将返回实际值。在此之前,tkinter无法确定尺寸,因为它取决于包装/放置/网格选项。谢谢@Bryan,我更新了答案以澄清这一点!