Warum ist meine PyObjC Cocoa Ansichtsklasse zu vergessen seine Felder?
Frage
Ich habe versucht, ein Werkzeug zu hacken bis zu Shadern für mein Spiel zu visualisieren und ich dachte, ich würde versuchen, Python und Kakao verwenden. Ich habe zwar in eine Mauer von Sorten läuft. Vielleicht ist es mein etwas schlecht objektiven c verstehen, aber ich kann nicht diesen Code scheint für eine Ansicht zu erhalten Ich habe versucht, Arbeits schreiben:
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)
Es gibt diese, wenn sie ausgeführt:
{'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'
Es scheint, meine Renderer Variable zu verlieren, die man bedenkt nicht, dass überraschend ist, wie flippige die initWithFrame_ Code ist, aber das war etwas Xcode schien zu schreiben, die ich sinnvoll annehmen macht da Objective-C die init getrennt von alloc Idiom hat. Es ist immer noch seltsam es Python jedoch zu sehen.
Gibt es sowieso diese zu retten, oder soll ich es nehmen hinter dem Code es vergossen schießen und QT oder wxPython verwenden? Ich betrachtete Objective-C verwenden, aber ich möchte diese raffinierte swig Bindungen testen ich gerade kompiliert =)
Lösung
Je nachdem, was an anderer Stelle in Ihrer Anwendung geschieht, könnte Ihre Instanz tatsächlich kopiert zu werden.
In diesem Fall implementieren die copyWithZone
Methode, um sicherzustellen, dass die neue Kopie als auch den Renderer bekommt. (Caveat, während ich ein Python-Entwickler bin, und ein Objective-C Kakao Entwickler, habe ich nicht verwendet PyObjC mich, so kann ich sicher nicht sagen, wenn Sie copyWithZone
oder __copy__
Umsetzung werden sollte).
In der Tat ermöglicht eine copyWithZone
Methode in der Klasse mit einem Druck schiebend, Ihnen zu sagen, wenn die Methode aufgerufen wird und wenn das der Grund Renderer scheint verschwunden zu sein.
Bearbeiten : Base auf Ihrem Feedback, habe ich Ihren Code in ein leeren Xcode Python-Projekt eingefügt (nur etwas anderes für gv.CoreRenderer ersetzen, da ich das nicht tun haben), und es arbeitet mit einigen kleineren Modifikationen in Ordnung. Wie werden Instantiieren Sie Ihre SceneView?
In meinem Fall I:
- Erstellt ein leeres Xcode Projekt der Cocoa-Python-Vorlage mit
- eine neue Datei namens
SceneView.py
Erstellt. Ich klebte in Ihrem Code. - öffnete die
MainMenu.xib
Datei und zog eine NSOpenGLView Box auf das Fenster. - Mit dem NSOpenGLView ausgewählt wurde, ging ich in die Attribute-Inspektor und änderte die Klasse der Box
SceneView
- Zurück in Xcode, fügte ich
import SceneView
in der Einfuhr inmain.py
so dass die Klasse zur Verfügung stehen würde, wenn die xib-Datei geladen wird - Ich implementierte eine
awakeFromNib
Methode inSceneView.py
Einrichtungself.renderer
zu handhaben. Beachten Sie, dass__init__
undinitWithFrame
sind nicht für nib Objekte während der Programmausführung genannt ... sie werden als „serialisiert“ in die Nib-Datei und damit bereits instanziiert. Ich polier einige Details über, aber das ist, warum awakeFromNib vorhanden ist. - Alles funktionierte auf Lauf. Die
__dict__
hatte die entsprechenden Werte in demdrawRect_
Aufruf, und so weiter.
Hier ist die awakeFromNib Funktion:
def awakeFromNib(self):
print "Awake from nib"
self.renderer = gv.CoreRenderer()
Also, ich vermute, es sind nur einige gekreuzten Drähte irgendwo in, wie Sie Ihr Objekt wird instanziiert und / oder zu der Ansicht hinzugefügt. Verwenden Sie Interface Builder für Ihr Objekt, oder sind Sie es manuell Erstellen und Hinzufügen es später zu einer Ansicht? Ich bin gespannt zu sehen, dass Sie loggin Ausgaben von Initwithframe bekommen, weshalb ich frage, wie Sie die SceneView erstellen.
Andere Tipps
Auch wenn sie nicht serialisiert waren, der __init __- Konstruktor von Python ist nicht durch die Objective-Brücke unterstützt. So muss man zum Beispiel, um eine Überlastung Initwithframe:. für selbst erstellte Ansichten