1

我试图破解一个工具来可视化我的游戏的着色器,我想我会尝试使用 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 习语分开。然而,看到它 python 仍然很奇怪。

有没有办法挽救这个,或者我应该在代码棚后面把它拿出来拍摄它并使用 QT 或 wxPython?我考虑过使用objective-c,但我想测试我刚刚编译的这些漂亮的swig绑定=)

4

2 回答 2

3

根据您的应用程序中其他地方发生的情况,您的实例实际上可能会被复制。

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

事实上,copyWithZone通过 print 将方法推入类中,您可以判断该方法是否正在被调用,以及这是否是渲染器似乎消失的原因。


编辑:根据您的反馈,我已将您的代码粘贴到一个空白的 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 对象调用 , 和 ......它们被认为是“序列化”到 nib 文件中,因此已经实例化__init__initWithFrame我在掩饰一些细节,但这就是 awakeFromNib 存在的原因。
  • 一切正常运行。在调用__dict__中有适当的值drawRect_,等等。

这是 awakeFromNib 函数:

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

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

于 2009-04-04T11:14:01.040 回答
2

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

于 2009-04-04T19:28:33.223 回答