我正在尝试为游戏编写代码,但是我在加载视频时遇到了一些麻烦。运行代码时出现此错误。我知道以前曾问过类似的问题,但我在这里找不到问题。当我运行代码时,会播放视频的前几秒钟,然后屏幕变成空白,并弹出此错误。
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/project_files/main_game2.py", line 69, in update
photo = ImageTk.PhotoImage(image=img)
File "C:\Users\jovan\AppData\Local\Programs\Python\Python38-32\lib\site-packages\PIL\ImageTk.py", line 112, in __init__
self.__photo = tkinter.PhotoImage(**kw)
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "C:\Users\jovan\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 4006, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: not enough free memory for image buffer
Exception ignored in: <function PhotoImage.__del__ at 0x03C570B8>
Traceback (most recent call last):
File "C:\Users\jovan\AppData\Local\Programs\Python\Python38-32\lib\site-packages\PIL\ImageTk.py", line 118, in __del__
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
我尝试运行部分与类分开加载和显示视频的代码,然后运行良好。我不知道发生了什么事,因为我是opencv和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("project_files\\video.mp4")
width = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
def get_frame():
ret,frame = vid.read()
if ret :
return(ret,cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
else :
return(ret,None)
def update():
canvas = Canvas(root, width = width, height = height)
canvas.place(relx=0.5,rely=0.5,anchor=CENTER)
ret,frame = get_frame()
if ret :
img = Image.fromarray(frame)
photo = ImageTk.PhotoImage(image=img)
photo.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("project_files\\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_files\\research.PNG"))
img_c = ImageTk.PhotoImage(Image.open("project_files\\com_ppl.PNG"))
img_i = ImageTk.PhotoImage(Image.open("project_files\\money.PNG"))
img_m = ImageTk.PhotoImage(Image.open("project_files\\military.PNG"))
img_p = ImageTk.PhotoImage(Image.open("project_files\\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("project_files\\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()
谢谢!
答案 0 :(得分:0)
问题在于,每次调用update()时我都在创建一个新列表,并且所有这些列表都在内存中堆积。我通过调用一个函数来解决问题,每次调用update()时,该函数都会破坏屏幕上当前所有的小部件。工作代码的相关部分在下面给出
def clear(self):
for widget in root.winfo_children():
widget.destroy()
def intro(self):
Game.clear(self)
vid = cv2.VideoCapture("project_files\\video.mp4")
width = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
def get_frame():
ret,frame = vid.read()
if ret :
return(ret,cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
else :
return(ret,None)
def update():
Game.clear(self) #i added this to delete the labels.
ret,frame = get_frame()
print(ret)
if ret :
img = Image.fromarray(frame)
photo = ImageTk.PhotoImage(image=img)
photo.image=img
label = Label(root,image=photo)
label.place(relx=0.5,rely=0.5,anchor=CENTER)
label.image=photo
root.after(delay,update)
delay = 15
update()
Game.qn_call(self,"a",iteration=0)