Python Tkinter框在重新绘制时移动

Python Tkinter框在重新绘制时移动,python,tkinter,game-physics,Python,Tkinter,Game Physics,我有一个程序,通过销毁Tkinter画布,然后再重新绘制,从而重新绘制Tkinter画布。但是,每次它绘制长方体时,都会向屏幕右侧移动几个像素。例如,如果第一个框齐平地绘制到屏幕的左侧,大约十个框之后绘制,则它现在齐平到屏幕的右侧。这是什么原因造成的?我如何才能阻止它 请注意,我在Mac上运行这一切,我遇到了一些在Tkinter中不能正常工作的问题,所以如果你知道这就是问题所在,请告诉我。感谢您的帮助,如果您需要任何其他信息,请随时询问 按照布莱恩·奥克利的建议,我不再破坏框架,只破坏矩形。然而

我有一个程序,通过销毁Tkinter画布,然后再重新绘制,从而重新绘制Tkinter画布。但是,每次它绘制长方体时,都会向屏幕右侧移动几个像素。例如,如果第一个框齐平地绘制到屏幕的左侧,大约十个框之后绘制,则它现在齐平到屏幕的右侧。这是什么原因造成的?我如何才能阻止它

请注意,我在Mac上运行这一切,我遇到了一些在Tkinter中不能正常工作的问题,所以如果你知道这就是问题所在,请告诉我。感谢您的帮助,如果您需要任何其他信息,请随时询问

按照布莱恩·奥克利的建议,我不再破坏框架,只破坏矩形。然而,现在我有一个问题,框架是画出来的,永远是空的。。。我不明白为什么

代码: 为了符合布莱恩·奥克利的建议,我做了一些改变。现在我在
w处得到错误
TclError:invalid command name“.4332933704”
create_rectangle(x,y,z,a,fill=“white”)

def打印板(时间,板):
全球w
全局根
x=20
y=15
z=60
a=45
对于范围内的i(透镜(板)-3,-1,-1):
y+=30
a+=30
x=20
z=60
对于范围内的j(len(板[i]):
x+=40
z+=40
如果len(board[i][j])==0:
w、 创建矩形(x、y、z、a、fill=“白色”)
其他:
w、 创建_矩形(x,y,z,a,fill='black')
root.after(整数(时间*1000),tech)
def tech():
全球w
w、 删除(全部)
def输出(电路板,难度):
全局根
全球w
root=Tk()
root.lift()
root.title(‘俄罗斯方块’)
w=画布(根,宽度=500,高度=750)
w、 全部绑定(“”,旋转)
w、 全部绑定(“”,左)
w、 绑定所有(“”,右)
w、 绑定所有(“”,停止)
w、 包()
mainloop()
全球比赛
玩=真
印刷电路板(第二节,电路板)
玩的时候:
游戏(棋盘)
印刷电路板(第二节,电路板)

您的第一个问题是每次迭代都要重新初始化整个GUI。特金特不想这样工作。这样做将产生不可预测的结果。您应该只创建一个
Tk
实例!并准确调用
mainloop

“盒子”每次都在移动的事实可能与此有关,如果“盒子”指的是窗口。如果不指定位置,则每次创建窗口时,某些windw管理器都会执行此操作


此外,删除并重新创建小部件是非常不寻常的——至少它速度慢且效率低。有用于移动对象的画布命令,或者如果确实需要,可以删除和重新创建画布项目

我在对您的原始代码进行了一系列编辑之后才写下这个答案。修复代码的唯一方法是完全重写它,而这不是本论坛的目的

我建议你停止编写你的程序,在Tkinter上学习一些教程(这是一个很好的开始)。您对事件驱动编程有一个基本的误解。例如,您在调用
mainloop
之后有代码,但调用
mainloop
必须是程序中最后一行逻辑代码。正是您试图在退出
mainloop
后创建小部件的事实导致了最新的错误(TclError:无效的命令名“.4332933704”)

其次,程序中有一个无限循环。事件驱动的程序已经有一个以事件循环形式存在的无限循环。这就是
mainloop
的功能。拥有自己的无限循环是错误的做法。您的程序需要基于事件,而不是硬编码的无限循环

如果希望每N毫秒触发一次重画,可以使用
after
tkinter方法来安排将来调用的函数。如果该函数做同样的事情(即:在将来某个时候调用自己),那么您已经内置了一个简单的动画循环。例如:

class MyApp(...):
    def __init__(...):
        # call it the first time; it will then call 
        # itself several times a second
        self.redraw()

    def redraw(self, *args):
        <redraw everything>
        self.after(42, self.redraw)
类MyApp(…):
定义初始化(…):
#第一次叫它;然后它会打电话
#一秒钟会有好几次
self.redraw()
def重绘(自身,*参数):
self.after(42,self.redraw)

除非您向我们展示您的代码,否则我们无法确定是什么bug导致了这种行为。Tkinter画布坚如磐石,因此问题几乎肯定在于您的代码。@chaosphenix7我认为如果画布
w
不存在,您现在描述的错误可能会发生。如果您的程序在
输出之前调用
打印板
,则会发生这种情况。(你可以通过添加
print
语句来检查这一点。)@chaosphenix7我也对
mainloop()之后的代码感到困惑。在tkinter窗口关闭之前,您无法访问此窗口。粘贴代码是错误的吗?@garycomtois我移动了
mainloop()
。我不知道为什么我把它放在我放的地方。我的程序初始化了框架并使其成功地创建了矩形,但实际创建矩形失败。我得到了我在上面发布的错误。在
output
@chaosphenix7之前未调用
printBoard
,我看到一个错误
w.pack
应该是
w.pack()
。这会改变你的结果吗?
class MyApp(...):
    def __init__(...):
        # call it the first time; it will then call 
        # itself several times a second
        self.redraw()

    def redraw(self, *args):
        <redraw everything>
        self.after(42, self.redraw)