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

发布于 2024-07-16 07:28:41 字数 1696 浏览 4 评论 0原文

我试图开发一个工具来可视化我的游戏的着色器,我想我会尝试使用 python 和 cocoa。 不过,我也遇到过类似的砖墙。 也许是我对 Objective 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 写的,我认为这是有意义的,因为 Objective C 将 init 与 alloc 习惯用法分开。 不过看到它是蟒蛇还是很奇怪。

有什么办法可以挽救这个吗?或者我应该把它放在代码库后面拍摄并使用 QT 或 wxPython? 我考虑过使用 Objective-C,但我想测试一下我刚刚编译的这些漂亮的 swig 绑定 =)

I was trying to hack up a tool to visualize shaders for my game and I figured I would try using python and cocoa. I have ran into a brick wall of sorts though. Maybe its my somewhat poor understand of objective c but I can not seem to get this code for a view I was trying to write working:

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)

It outputs this when executed:

{'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'

It seems to be losing my renderer variable which is not that surprising considering how funky the initWithFrame_ code is but this was something xcode seemed to write which I suppose makes sense since objective C has the init separate from alloc idiom. It is still strange seeing it python however.

Is there anyways to salvage this or should I take it out behind the code shed shoot it and use QT or wxPython? I considered using objective-c but I want to test out these nifty swig bindings I just compiled =)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时常饿 2024-07-23 07:28:41

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

在这种情况下,请实现 copyWithZone 方法以确保新副本也获得渲染器。 (注意,虽然我是一名 Python 开发人员和 Objective-C cocoa 开发人员,但我自己没有使用过 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 文件时该类可用
  • 我在 SceneView.py 中实现了一个 awakeFromNib 方法来处理设置 self.renderer。 请注意,在程序执行期间,不会为 nib 对象调用 __init__initWithFrame...它们被视为“序列化”到 nib 文件中,因此已经实例化。 我掩盖了一些细节,但这就是 awakeFromNib 存在的原因。
  • 一切都在运行中进行。 __dict__drawRect_ 调用中具有适当的值,等等。

这是 awakeFromNib 函数:

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

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

Depending on what's happening elsewhere in your app, your instance might actually be getting copied.

In this case, implement the copyWithZone method to ensure that the new copy gets the renderer as well. (Caveat, while I am a Python developer, and an Objective-C cocoa developer, I haven't used PyObjC myself, so I can't say for certain if you should be implementing copyWithZone or __copy__).

In fact, shoving a copyWithZone method into the class with a print will allow you to tell if the method is being called and if that's the reason renderer appears to have vanished.


Edit: Base on your feedback, I've pasted your code into a blank xcode python project (just substituting something else for gv.CoreRenderer, since I don't have that), and it works fine with some minor modifications. How are you instantiating your SceneView?

In my case I:

  • Created a blank xcode project using the Cocoa-Python template
  • Created a new file called SceneView.py. I pasted in your code.
  • Opened the MainMenu.xib file, and dragged an NSOpenGLView box onto the window.
  • With the NSOpenGLView box selected, I went to the attributes inspector and changed the class of the box to SceneView
  • Back in xcode, I added import SceneView in the imports in main.py so that the class would be available when the xib file is loaded
  • I implemented an awakeFromNib method in SceneView.py to handle setting up self.renderer. Note that __init__, and initWithFrame are not called for nib objects during your program execution... they are considered "serialized" into the nib file, and therefore already instantiated. I'm glossing over some details, but this is why awakeFromNib exists.
  • Everything worked on run. The __dict__ had appropriate values in the drawRect_ call, and such.

Here's the awakeFromNib function:

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

So, I'm guessing there are just some crossed wires somewhere in how your object is being instantiated and/or added to the view. Are you using Interface Builder for your object, or are you manually creating it and adding it to a view later? I'm curious to see that you are getting loggin outputs from initWithFrame, which is why I'm asking how you are creating the SceneView.

霞映澄塘 2024-07-23 07:28:41

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

Even if they weren't serialized, the __init__-constructor of python isn't supported by the ObjectiveC-bridge. So one needs to overload e.g. initWithFrame: for self-created Views.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文