为什么我的PyObjc Cocoa视图类忘记了它的字段?

时间:2009-04-04 02:33:11

标签: python xcode macos pyobjc

我试图破解一个工具来为我的游戏可视化着色器,我想我会尝试使用python和cocoa。我碰到了一堵砖墙。也许是我对目标c的理解有点差,但我似乎无法将这段代码用于我试图编写的视图:

from objc import YES, NO, IBAction, IBOutlet
from Foundation import *
from AppKit import *
import gv

class SceneView(NSOpenGLView):
    def __init__(self):
        NSOpenGLView.__init__(self)
        self.renderer = None

    def doinit(self):
        self.renderer = gv.CoreRenderer()


    def initWithFrame_(self, frame):
        self = super(SceneView, self).initWithFrame_(frame)

        if self:
            self.doinit()
            print self.__dict__

        return self

    def drawRect_(self, rect):
        clearColor = [0.0,0.0,0.0,0.0]
        print self.__dict__
        self.renderer.clear(CF_Target|CF_ZBuffer,clearColor)

执行时输出:

{'renderer': <gv.CoreRenderer; proxy of <Swig Object of type 'GV::CoreRenderer *' at 0x202c7d0> >}
{}
2009-04-03 19:13:30.941 geom-view-edit[50154:10b] An exception has occured:
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjCTools/AppHelper.py", line 235, in runEventLoop
  File "/mnt/gilead/amcharg/projects/geom-view-edit/build/Debug/geom-view-edit.app/Contents/Resources/SceneView.py", line 37, in drawRect_
    self.renderer.clear(CF_Target|CF_ZBuffer,clearColor)
AttributeError: 'SceneView' object has no attribute 'renderer'

似乎丢失了我的渲染器变量,考虑到initWithFrame_代码有多么简单,这并不令人惊讶,但这是xcode似乎写的东西,我认为这是有道理的,因为目标C将init与alloc惯用语分开。然而,看到它的蟒蛇仍然很奇怪。

是否有任何方法可以挽救这一点,还是应该在代码棚后面拍摄并使用QT或wxPython?我考虑过使用objective-c,但我想测试一下我刚编译的这些漂亮的swig绑定=)

2 个答案:

答案 0 :(得分:3)

根据您应用中其他位置发生的情况,您的实例可能实际上已被复制。

在这种情况下,请实现copyWithZone方法以确保新副本也获得渲染器。 (请注意,虽然我是Python开发人员和Objective-C可可开发人员,但我自己没有使用过PyObjC,所以我不能肯定你是否应该实现copyWithZone__copy__ )。

事实上,将copyWithZone方法推入带有打印的类中将允许您判断是否正在调用该方法,以及这是渲染器似乎消失的原因。


编辑:根据您的反馈,我已将您的代码粘贴到一个空白的xcode python项目中(只是用其他东西代替gv.CoreRenderer,因为我没有这个),并且它通过一些小的修改工作正常。你如何实例化你的SceneView?

在我的情况下我:

  • 使用Cocoa-Python模板
  • 创建了一个空白的xcode项目
  • 创建了一个名为SceneView.py的新文件。我粘贴了你的代码。
  • 打开MainMenu.xib文件,将NSOpenGLView框拖到窗口上。
  • 选中NSOpenGLView框后,我转到属性检查器并将框的类更改为SceneView
  • 回到xcode,我在import SceneView的导入中添加了main.py,以便在加载xib文件时该类可用
  • 我在awakeFromNib中实施了SceneView.py方法来处理设置self.renderer。请注意,在程序执行期间,不会为nib​​对象调用__init__initWithFrame ...它们被视为“序列化”到nib文件中,因此已经实例化。我正在浏览一些细节,但这就是awakeFromNib存在的原因。
  • 一切都在运行。 __dict__drawRect_调用中具有适当的值,等等。

这是awakeFromNib函数:

def awakeFromNib(self):
    print "Awake from nib"
    self.renderer = gv.CoreRenderer()

所以,我猜测在你的对象被实例化和/或添加到视图中的某些地方只有一些交叉的线。您是使用Interface Builder作为对象,还是手动创建它并稍后将其添加到视图中?我很想知道你是从initWithFrame获取loggin输出的,这就是我问你如何创建SceneView的原因。

答案 1 :(得分:2)

即使它们没有被序列化,ObjectiveC-bridge也不支持python的__init __-构造函数。所以需要重载例如initWithFrame:用于自创视图。