Почему мой класс представления PyObjc Cocoa забывает свои поля? - PullRequest
1 голос
/ 04 апреля 2009

Я пытался взломать инструмент для визуализации шейдеров для своей игры и решил, что попробую использовать питон и какао. Я наткнулся на какую-то кирпичную стену. Может быть, это мое несколько плохое понимание цели 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 idiom. Однако все еще странно видеть этого питона.

Есть ли в любом случае, чтобы спасти это, или я должен вынуть его за код сарай снимать его и использовать QT или wxPython? Я подумал об использовании target-c, но я хочу проверить эти изящные привязки swig, которые я только что скомпилировал =)

Ответы [ 2 ]

3 голосов
/ 04 апреля 2009

В зависимости от того, что происходит в другом месте вашего приложения, ваш экземпляр может быть скопирован.

В этом случае реализуйте метод copyWithZone, чтобы новая копия также получала средство визуализации. (Предостерегаю, хотя я являюсь разработчиком на Python и разработчиком какао для Objective-C, я сам не использовал PyObjC, поэтому не могу с уверенностью сказать, следует ли вам реализовать copyWithZone или __copy__).

Фактически, добавление метода copyWithZone в класс с печатью позволит вам определить, вызывается ли метод и по этой причине средство рендеринга исчезло.


Редактировать : Основываясь на ваших отзывах, я вставил ваш код в пустой проект xcode python (просто подставляя что-то еще для gv.CoreRenderer, поскольку у меня его нет), и это работает хорошо с некоторыми незначительными изменениями. Как вы создаете экземпляр своего SceneView?

В моем случае я:

  • Создан пустой проект xcode с использованием шаблона Cocoa-Python
  • Создан новый файл с именем SceneView.py. Я вставил в ваш код.
  • Открыл файл MainMenu.xib и перетащил окно NSOpenGLView в окно.
  • С выбранным полем NSOpenGLView я пошел в инспектор атрибутов и изменил класс поля на SceneView
  • Вернувшись в xcode, я добавил import SceneView в импорт в main.py, чтобы класс был доступен при загрузке xib-файла
  • Я реализовал метод awakeFromNib в SceneView.py для обработки self.renderer. Обратите внимание, что __init__ и initWithFrame не вызываются для объектов пера во время выполнения вашей программы ... они считаются "сериализованными" в файл пера, и, следовательно, уже созданы. Я закрываю некоторые детали, но именно поэтому существует awakeFromNib.
  • Все работало на бегу. У __dict__ были соответствующие значения в вызове drawRect_, и тому подобное.

Вот функция awakeFromNib:

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

Итак, я предполагаю, что где-то в том, как ваш объект создается и / или добавляется в представление, есть только несколько скрещенных проводов. Используете ли вы Interface Builder для своего объекта, или вы вручную создаете его и добавляете в представление позже? Мне любопытно видеть, что вы получаете выходные данные loggin от initWithFrame, поэтому я спрашиваю, как вы создаете SceneView.

2 голосов
/ 04 апреля 2009

Даже если они не были сериализованы, __init __- конструктор python не поддерживается ObjectiveC-bridge. Так что нужно перегружать, например, initWithFrame: для самостоятельно созданных представлений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...