我在覆盆子pi上使用Python中的pi3d lib。我要做的是动态创建屏幕对象,并替换它们。 首先,我想填写一系列字典。这些可以是整数,字符串或pi3D精灵对象。 我有以下测试代码:
import pi3d
DISPLAY = pi3d.Display.create(x=0, y=0)
shader = pi3d.Shader("uv_flat")
CAMERA = pi3d.Camera(is_3d=False)
screen_items=[]
for item_number in range (5):
screen_item={}
screen_item['type']= 'second_rotation_stepped'
screen_item['text_type']='static'
screen_item['visible']='always'
screen_item['image_sprite']=pi3d.ImageSprite(pi3d.Texture("textures/PATRN.PNG", blend=True), shader, w=100.0, h=100.0, z=5.0 ,x=0,y=120*item_number)
screen_items.append(screen_item)
screen_items[0]['image_sprite']=pi3d.ImageSprite(pi3d.Texture("textures/altimeter.png", blend=True), shader, w=50.0, h=50.0, z=5.0 ,x=0,y=-200)
screen_items[0]['visible']='never'
screen_items[2]['image_sprite'].rotateToZ(45)
mykeys = pi3d.Keyboard()
while DISPLAY.loop_running():
for drawitem in screen_items:
drawitem['image_sprite'].draw()
if mykeys.read() == 27:
mykeys.close()
DISPLAY.destroy()
Break
一切都按照我的预期运作,但它给了我一个错误/警告: “无法设置删除”
如果我阻止代码,则不会出现此错误:
screen_items[0]['image_sprite']=pi3d.ImageSprite(pi3d.Texture("textures/altimeter.png", blend=True), shader, w=50.0, h=50.0, z=5.0 ,x=0,y=-200)
我的代码不会出现此错误:
screen_items[0]['visible']='never'
所以我想我可以替换字典中的字符串,但不能替换对象? 就像我说的,一切正常,对象确实被替换(并在屏幕上绘制)但不知何故“旧”对象不会被删除。它是某种指针问题吗?
答案 0 :(得分:1)
"错误"您尝试删除脚本中for循环中创建的初始Texture
对象时,pi3d实际上是一个调试消息。
当您将新的ImageSprite
对象重新分配给screen_items[0]['image_sprite']
时,旧的Texture
对象会被垃圾回收,并调用它的__del__
方法,导致此问题调试消息。
参考:https://github.com/tipam/pi3d/blob/master/pi3d/Texture.py#L87
答案 1 :(得分:0)
这个问题起源是因为python垃圾收集器没有整理创建Texture实例时分配的gpu内存。
在python中,可以使用__del__()
方法作为析构函数,但它不一定立即执行。当第一次观察到gpu缓冲区内存泄漏时,它被a bug in the video core due to implementation of EGL混淆了,所以pi3d最终得到了一条腰带和大括号'系统,其中引用在Display对象中保存到所有纹理,顶点和元素缓冲区,如果在关闭时,任何这些都没有被python对象释放。 __del__()
方法,最终明确了。
然而,在某些情况下,非常偶然地,当程序关闭时,引用指向在它们可以删除对自己的引用之前已经释放的对象。由于这个bug对运行代码没有任何影响,因此很难理清它已经被放在了后面。
PS请参阅raspberry pi论坛帖子t = 79383,以便我解决@ satoer的问题