首页 > 解决方案 > _tkinter.TclError:无效的命令名称“.!canvas”

问题描述

我正在尝试制作游戏,但在我的游戏中加载视频时遇到了一些问题。我知道之前有人问过一些类似的问题,但我无法对我的问题得到满意的解释。这是我运行代码时遇到的错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\jovan\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "C:\Users\jovan\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 804, in callit
    func(*args)
  File "c:/Jovan/Pycharm Projects/school projects/main_game2.py", line 70, in update
    canvas.create_image(0, 0, image = photo, anchor = NW)
  File "C:\Users\jovan\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 2785, in create_image
    return self._create('image', args, kw)
  File "C:\Users\jovan\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 2771, in _create
    return self.tk.getint(self.tk.call(
_tkinter.TclError: invalid command name ".!canvas"

问题似乎出现在函数中,intro()但我似乎找不到原因的答案。为什么会这样?我该如何解决这个问题?我是新手,tkinter所以请尽量保持简单。代码如下:'''

from tkinter import * 
from tkinter import messagebox
from random import *
from PIL import ImageTk,Image 
import cv2
                                    
root = Tk()                            
root.title("Captain!") 
root.geometry("1280x720")
#root.geometry("660x560")

class Game :
    def __init__(self): 
        self.m_cur = {1:["Military",50]} 
        self.c_cur = {1:["People's",50]}
        self.r_cur = {1:["Research",50]}      
        self.i_cur = {1:["Industrial",50]}           
        self.p_cur = {1:["Research",50]}

    def clear(self):
        for widget in root.winfo_children():        
            widget.destroy() 

    def exit(self):
        msg = messagebox.askquestion("Thank you for playing","Are you sure you want to exit?")
        if msg == "yes" :
            root.destroy()
        else:
            Game.main(self)
                                    
    def start(self):
        Label(root,text="Hello, what should we call you?",font=("segoe print",20)).grid(row=0,column=0)
        name = Entry(root,width=20)
        name.grid(row=1,column=0) 
        Button(root,text="Enter",font=("segoe print",20),command=lambda: Game.main(self)).grid(row=1,column=1)
        self.name=name.get() 
   
    def main(self):
        Game.clear(self)
        Label(root,text="Welcome to the game",font=("segoe print",20)).grid(row=0,column=0)
        Label(root,text='What do you want to do?',font=("segoe print",20)).grid(row=1,column=0)
        qn_num = randint(1,3)
        Button(root,text="Start Game",font=("segoe print",20),command=lambda: Game.intro(self,qn_num)).grid(row=2,column=0)
        Button(root,text="Exit Game",font=("segoe print",20),command=lambda: Game.exit(self)).grid(row=3,column=0)
        #resetting values of the variables
        self.r_cur[1][1] = 50
        self.c_cur[1][1] = 50
        self.i_cur[1][1] = 50
        self.m_cur[1][1] = 50
        self.p_cur[1][1] = 50

    def intro(self,qn_num):
        Game.clear(self)
        vid = cv2.VideoCapture("video.mp4")
        width = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
        height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
        canvas = Canvas(root, width = width, height = height)
        canvas.pack()
        def get_frame():
            ret,frame = vid.read()
            if ret :
                return(ret,cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
            else :
                return(ret,None)
        def update():
            ret,frame = get_frame()
            if ret :
                img = Image.fromarray(frame)
                photo = ImageTk.PhotoImage(image=img)
                canvas.create_image(0, 0, image = photo, anchor = NW)
                canvas.image=photo
            root.after(delay,update)

        delay = 15
        update()
        Game.qn_func(self,qn_num)

    def game_over(self,x_cur):
        if x_cur[1][1]<=0 or x_cur[1][1]>=100 :
            Game.clear(self)
            Label(root,text=f"{x_cur[1][0]} faction rebelled").place(relx=0.4,rely=0.4)
            Label(root,text="GAME OVER",font=("ariel",20)).place(relx=0.5,rely=0.5,anchor=CENTER)
            Button(root,text="Continue",font=("segoe print",20),command=lambda: Game.main(self)).place(relx=0.37,rely=0.6)

    def qn_func(self,qn_num) :
        Game.clear(self)
        with open("questions_file.txt") as q_file :
            #reading the question, options, next qn numbers and the character name from the file
            qn_list = q_file.readlines() 
            qn = qn_list[qn_num-1].strip().split("$")[1]
            char_name = qn_list[qn_num-1].strip().split("$")[2]
            qn1 = qn_list[qn_num-1].strip().split("$")[3]
            qn2 = qn_list[qn_num-1].strip().split("$")[5]
            n_qn1 = int(qn_list[qn_num-1].strip().split("$")[4])
            n_qn2 = int(qn_list[qn_num-1].strip().split("$")[6])
        #displaying the character name and the question as a label frame widget with character name as parent
        label_frame = LabelFrame(root,text = char_name,font = ("segoe print",20))
        label = Label(label_frame,text = qn,font = ("segoe print",20))
        label_frame.place(relx=0.5,rely=0.5,anchor=CENTER)
        label.pack()
        #displaying the buttons on the screen
        Button(root,text=qn1,command=lambda: Game.qn_func(self,n_qn1)).place(relx=0.2,rely=0.7,anchor=W,width=200,height=50)
        Button(root,text=qn2,command=lambda: Game.qn_func(self,n_qn2)).place(relx=0.8,rely=0.7,anchor=E,width=200,height=50)
        #running each variable through game_over to see if you are dead
        Game.game_over(self,self.r_cur)
        Game.game_over(self,self.c_cur)
        Game.game_over(self,self.i_cur)
        Game.game_over(self,self.m_cur)
        Game.game_over(self,self.p_cur)
        #defining the Doublevar variables
        s_var1 = DoubleVar()
        s_var2 = DoubleVar()
        s_var3 = DoubleVar()
        s_var4 = DoubleVar()
        s_var5 = DoubleVar()                        
        #setting the values in the scales
        s_var1.set(self.r_cur[1][1])
        s_var2.set(self.c_cur[1][1])
        s_var3.set(self.i_cur[1][1])
        s_var4.set(self.m_cur[1][1])
        s_var5.set(self.p_cur[1][1])
        #variables as scale widgets
        scale1 = Scale(root,from_=100,to=0,orient=VERTICAL,sliderlength=10,variable=s_var1)
        scale2 = Scale(root,from_=100,to=0,orient=VERTICAL,sliderlength=10,variable=s_var2)
        scale3 = Scale(root,from_=100,to=0,orient=VERTICAL,sliderlength=10,variable=s_var3)
        scale4 = Scale(root,from_=100,to=0,orient=VERTICAL,sliderlength=10,variable=s_var4)
        scale5 = Scale(root,from_=100,to=0,orient=VERTICAL,sliderlength=10,variable=s_var5)
        #opening images to be displayed under scales
        img_r = ImageTk.PhotoImage(Image.open("project_pics\\research.PNG"))
        img_c = ImageTk.PhotoImage(Image.open("project_pics\\com_ppl.PNG"))
        img_i = ImageTk.PhotoImage(Image.open("project_pics\\money.PNG"))
        img_m = ImageTk.PhotoImage(Image.open("project_pics\\military.PNG"))
        img_p = ImageTk.PhotoImage(Image.open("project_pics\\productivity.PNG"))
        #the label widgets for images
        img_l1 = Label(root,image=img_r)
        img_l2 = Label(root,image=img_c)
        img_l3 = Label(root,image=img_i)
        img_l4 = Label(root,image=img_m)
        img_l5 = Label(root,image=img_p)
        #saving a reference of images
        img_l1.image = img_r
        img_l2.image = img_c
        img_l3.image = img_i
        img_l4.image = img_m
        img_l5.image = img_p
        #displaying images
        img_l1.grid(row=1,column=0)
        img_l2.grid(row=1,column=1)
        img_l3.grid(row=1,column=2)
        img_l4.grid(row=1,column=3)
        img_l5.grid(row=1,column=4)
        #displaying the scale widgets on the screen
        scale1.grid(row=0,column=0,padx=40,pady=10)
        scale2.grid(row=0,column=1,padx=40,pady=10)
        scale3.grid(row=0,column=2,padx=40,pady=10)
        scale4.grid(row=0,column=3,padx=40,pady=10)
        scale5.grid(row=0,column=4,padx=40,pady=10)
        #disabling the scales
        scale1.config(state=DISABLED)
        scale2.config(state=DISABLED)
        scale3.config(state=DISABLED)
        scale4.config(state=DISABLED)
        scale5.config(state=DISABLED)
        with open("variables.txt") as v_file :
            #reading values of variables from file
            v_list = v_file.readlines()
            self.r_cur[1][1] += int(v_list[qn_num-1].strip().split("$")[1])
            self.c_cur[1][1] += int(v_list[qn_num-1].strip().split("$")[2])
            self.i_cur[1][1] += int(v_list[qn_num-1].strip().split("$")[3])
            self.m_cur[1][1] += int(v_list[qn_num-1].strip().split("$")[4])
            self.p_cur[1][1] += int(v_list[qn_num-1].strip().split("$")[5])

#driver code
game = Game()
game.start()
root.mainloop()

'''

标签: pythonpython-3.xopencvtkinter

解决方案


你提到的问题,似乎有这个原因:
intro()调用qn_func(),调用clear()
clear()销毁所有小部件,它们是根的孩子。
你的画布是根的一个孩子。
=> 下一次调用update()找不到您的画布。


推荐阅读