这里的初学者试图讲解类。下面是我的班级单元格的代码:
import tkinter
import random
top = tkinter.Tk()
canvas = tkinter.Canvas(top, bg="grey", height=400, width=400)
canvas.pack()
class Cell:
def __init__(self, x, y, r):
self.x = random(x)
self.y = random(y)
self.r = 200
def show(self):
canvas.create_oval(self.x, self.y, self.r, self.r, fill = "blue")
top.mainloop()
我试图通过调用类中的show函数在主程序中绘制单元格。这是我的主窗口的代码:
import tkinter
top = tkinter.Tk()
canvas = tkinter.Canvas(top, bg="grey", height=400, width=400)
canvas.pack()
from Cell import Cell
cell = Cell()
cell.show()
top.mainloop()
这将导致正确绘制画布,但是找不到椭圆形。我也没有任何错误。
任何帮助将不胜感激。谢谢!
===================
结果是,我误解了create_oval
的参数。我找到了一些代码,可以将笨拙的create_oval
函数转换为一个函数,该函数接收一组针对椭圆中心和半径的坐标。
除此之外,我在理解类和其他Python功能方面获得的帮助也大有帮助。感谢那些帮助过的人!
这是我修改后的代码,可以正常使用。
import tkinter as tk
import random
top = tk.Tk()
canvas = tk.Canvas(top, width=400, height=400, bg="grey")
canvas.grid()
def _create_circle(self, x, y, r, **kwargs):
return self.create_oval(x-r, y-r, x+r, y+r, **kwargs)
tk.Canvas.create_circle = _create_circle
class Cell:
def __init__(self, canvas, x, y, r):
self.canvas = canvas
self.x = x
self.y = y
self.r = r
def show(self):
self.canvas.create_circle(self.x, self. y, self.r, fill = "blue")
cell = Cell(canvas, random.randrange(50, 350), random.randrange(50, 350), 25)
cell.show()
top.mainloop()
答案 0 :(得分:2)
这里的问题是您的主脚本和Cell
模块都在创建一个新的Tk
实例,向其中添加一个Canvas
,然后调用其mainloop
方法。
如果您跟踪执行语句的顺序,则会发现cell = Cell()
和cell.show()
直到第一个top.mainloop()
返回并且{{ 1}}直到您退出程序才返回。 (实际上,如果您的代码 did 达到了那么高的水平,它将失败并显示mainloop()
,我将在下面进行介绍。)
但是,更一般而言,您只需要在程序中使用一个TypeError
,其他所有人都应该引用它。
在这种情况下,您希望Tk
拥有相同的功能:只有其中一个封装在一个Canvas
主窗口中。
那么,Tk
如何从另一个模块引用全局Cell.show
?
最好的解决方案是根本不将其称为全局变量,而是将其传递给初始化程序,就像使用canvas
,x
和{{1}一样。 }:
y
然后在主脚本中:
r
但是请注意我放在那里的class Cell:
def __init__(self, canvas, x, y, r):
self.canvas = canvas
self.x = random(x)
self.y = random(y)
self.r = 200
def show(self):
self.canvas.create_oval(self.x, self.y, self.r, self.r, fill = "blue")
。您的cell = Cell(canvas, ?, ?. ?)
cell.show()
类定义在其初始值设定项中需要?
,Cell
和x
值,但您的y
构造函数调用未传递任何值。这将引发r
抱怨您缺少必需的参数。
您想在这里通过什么?由于画布是400x400,也许您想要传递400、400、200之类的内容?如果是这样:
Cell()
回到该初始值设定项,那里还有其他问题:
TypeError
cell = Cell(canvas, 400, 400, 200)
cell.show()
是一个模块。您不能调用模块。您可能想要这样的东西:
self.x = random(x)
self.y = random(y)
该函数从random
模块调用一个函数,该函数定义为在self.x = random.randrange(x)
中返回一个随机数,这似乎是您想要的。
也:
random
为什么要使用range(0, x)
参数,而忽略它?您可能想要这样:
self.r = 200
或者,也许您实际上并不想使用r
,self.r = r
和x
作为参数?也许您想对y
,r
和randrange(400)
进行硬编码,或者您想根据randrange(400)
参数的宽度和高度来计算它们,或者...可以几乎所有您想要的东西,您都只需要仔细考虑您想要的东西,并确保在200
中声明的接口与稍后在canvas
中调用它的方式相匹配。
答案 1 :(得分:1)
我认为您的执行路径永远不会到达cell.show()
行。
导入Cell
时,您将在顶级top.mainloop()
上拥有代码。这会进入主循环,并且永远不会退出,因此您永远都不会到达主循环下面的行。
避免将代码置于基础级别是一个很好的经验法则。保留用于定义类和函数的内容。如果要使代码像脚本一样在调用文件时运行,请将其置于if __name__ == __main__:
状态。
使用随机数并调用Cell构造函数时,您还会遇到一些语法问题。 下面的示例按预期方式工作。
import tkinter
import random
top = tkinter.Tk()
canvas = tkinter.Canvas(top, bg="grey", height=400, width=400)
canvas.pack()
class Cell:
def __init__(self, x, y, r):
self.x = x
self.y = y
self.r = r
def show(self):
canvas.create_oval(self.x, self.y, self.r, self.r, fill = "blue")
if __name__ == "__main__":
cell = Cell(100, 50, 5)
cell.show()
top.mainloop()