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 には alloc イディオムとは別の init があるため、理にかなっていると思います。しかし、それでもpythonを見るのは奇妙です。

とにかくこれを救う方法はありますか、それともコード小屋の後ろに取り出してQTまたはwxPythonを使用する必要がありますか? Objective-C の使用を検討しましたが、コンパイルしたばかりの気の利いた swig バインディングをテストしたいと思います =)

4

2 に答える 2

3

アプリの他の場所で何が起こっているかによっては、インスタンスが実際にコピーされている可能性があります。

この場合、copyWithZoneメソッドを実装して、新しいコピーもレンダラーを確実に取得するようにします。(注意してください、私は Python 開発者であり、Objective-C ココア開発者ですが、PyObjC を自分で使用したことがないため、copyWithZoneまたはを実装する必要があるかどうかはわかりません__copy__)。

実際、copyWithZoneprint を使用してメソッドをクラスに押し込むと、メソッドが呼び出されているかどうか、それが原因でレンダラーが消えたように見えるかどうかがわかります。


編集:あなたのフィードバックに基づいて、あなたのコードを空のxcode pythonプロジェクトに貼り付けました(gv.CoreRendererを持っていないので、別のものに置き換えただけです)。いくつかの小さな変更で正常に動作します。SceneView をどのようにインスタンス化していますか?

私の場合、私は:

  • Cocoa-Python テンプレートを使用して空の xcode プロジェクトを作成しました
  • という名前の新しいファイルを作成しましたSceneView.py。あなたのコードを貼り付けました。
  • ファイルを開き、 NSOpenGLViewMainMenu.xibボックスをウィンドウにドラッグしました。
  • NSOpenGLView ボックスを選択した状態で、属性インスペクタに移動し、ボックスのクラスを次のように変更しました。SceneView
  • xcodeに戻り、xibファイルがロードされたときにクラスが利用できるようにimport SceneView、インポートを追加しましたmain.py
  • の設定を処理するawakeFromNibメソッドを実装しました。、およびは、プログラムの実行中に nib オブジェクトに対して呼び出されないことに注意してください... これらは、nib ファイルに「シリアル化」されていると見なされるため、既にインスタンス化されています。詳細については省略していますが、これが awakeFromNib が存在する理由です。SceneView.pyself.renderer__init__initWithFrame
  • すべてが実行中に機能しました。呼び出しなど__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

シリアル化されていない場合でも、python の __init__ コンストラクターは ObjectiveC ブリッジではサポートされていません。したがって、自分で作成したビューの場合は、initWithFrame: などをオーバーロードする必要があります。

于 2009-04-04T19:28:33.223 に答える