首页 > 解决方案 > Python`Ошибка无效的命令名“.!canvas”`

问题描述

我正在尝试教孩子们用 Python 编程。我自己不认识他。我们开始很简单,球在屏幕上弹跳。我们发现了一个错误,谷歌没有帮助。

Traceback (most recent call last):
  File "C:\Users\KrehtaFamily\Desktop\Programms\kirr\first.py", line 54, in <module>
    MoveBall()
  File "C:\Users\KrehtaFamily\Desktop\Programms\kirr\first.py", line 39, in MoveBall
    PaintBall(1,x_start,y_start)
  File "C:\Users\KrehtaFamily\Desktop\Programms\kirr\first.py", line 23, in PaintBall
    holst.create_oval(x_coord, y_coord, x_coord+30, y_coord+30, fill=fill_color, outline=out_color)#Рисуем мяч на холсте
  File "C:\Users\KrehtaFamily\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 2798, in create_oval
    return self._create('oval', args, kw)
  File "C:\Users\KrehtaFamily\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 2776, in _create
    return self.tk.getint(self.tk.call(
_tkinter.TclError: invalid command name ".!canvas"

我们需要一个无限的窗口重绘循环。创建了一个无限循环。通过调用 Tk.update() 进行渲染。结果,如果您单击十字关闭窗口,则会弹出错误。很明显,问题是不正确的终止。我尝试了这些选项。无用。如何正确完成。可以得分,程序有效,但原则要求您了解并修复错误:) 下面的脚本

from tkinter import *
import time

def on_closing():
    global window
    window.destroy()  # Закрыть окно

def PaintBall(paint_command, x_coord, y_coord):
    '''
    Функция PaintBell - Рисование мяча на экране
    paint_command - 1- Нарисовать мяч, красным. 2 - Нарисовать мяч черным
    x_coord - Координата X
    y_coord - Координата Y
    '''
    global holst
    global window
    if paint_command == 1:
        fill_color = 'red'
        out_color = 'white'
    else:
        fill_color = 'black'
        out_color = 'black'
    holst.create_oval(x_coord, y_coord, x_coord+30, y_coord+30, fill=fill_color, outline=out_color)#Рисуем мяч на холсте
    time.sleep(0.1)
    window.update()
    

def MoveBall():
    global x_start
    global y_start
    global step
    PaintBall(2,x_start,y_start)
    x_start=x_start+step
    if (x_start+step) > 170:
        step = -10
    elif (x_start+step) < 1:
        step = 10
    x_start=x_start+step
    PaintBall(1,x_start,y_start)

x_start=100
y_start=100
step=10
window = Tk() #Создаем окно
window.title("Сбежавший мячик!!!") #Выводим название программы в окне
window.geometry("200x200+100+100") #задаем размер окна
window.protocol("WM_DELETE_WINDOW", on_closing)
holst = Canvas(window, width=200, height=200, bg='black') #Задаем окно, размер, и цвет холста
holst.pack() #Рисуем холст в окне
PaintBall(1,x_start,y_start)

a = 1
while a < 5:
    MoveBall()
tk.mainloop()

标签: tkinter

解决方案


您的代码存在许多问题。

您的函数每次被调用时都会PaintBall创建一个新对象。oval

您使用time.sleep的是干扰tkinter事件。

由于使用after设置为 50 毫秒并将球增量值从 10 减少到 5,代码现在可以处理平滑动画。

from tkinter import *

def on_closing():
    global window
    window.destroy()  # Закрыть окно

def PaintBall(paint_command, x_coord, y_coord):
    '''
    Функция PaintBell - Рисование мяча на экране
    paint_command - 1- Нарисовать мяч, красным. 2 - Нарисовать мяч черным
    x_coord - Координата X
    y_coord - Координата Y
    '''
    global holst, window, ball
    if paint_command == 1:
        fill_color = 'red'
        out_color = 'white'
    else:
        fill_color = 'black'
        out_color = 'black'
    holst.coords(ball, x_coord, y_coord, x_coord+30, y_coord+30)
    holst.itemconfig(ball, fill = fill_color, outline = out_color)

def MoveBall(paint_command, x_start, y_start):
    global step
    PaintBall(paint_command, x_start, y_start)
    x_start=x_start+step
    if (x_start+step) > 170:
        step = -5
    elif (x_start+step) < 0:
        step = 5
    x_start=x_start+step
    # animation set to 50 milliseconds
    holst.after( 50, MoveBall, 1, x_start, y_start)

x_start=100
y_start=100
step=10
window = Tk() #Создаем окно
window.title("Сбежавший мячик!!!") #Выводим название программы в окне
window.geometry("200x200+100+100") #задаем размер окна
window.protocol("WM_DELETE_WINDOW", on_closing)
holst = Canvas(window, width=200, height=200, bg='black') #Задаем окно, размер, и цвет холста
holst.pack() #Рисуем холст в окне
# create ball ONCE
ball = holst.create_oval( 0, 0, 30, 30, fill = 'red', outline = 'white') #Рисуем мяч на холсте
# start the ball 'rolling'
holst.after( 100, MoveBall, 1, x_start, y_start)

window.mainloop()

推荐阅读