2009-05-10 11 views
3

Ich möchte ein NSOpenPanel für eine Anwendung verwenden, die ich entwerfe. Hier ist, was ich bisher:Wie stelle ich einen void-Zeiger in einem PyObjC-Selektor dar?

@objc.IBAction 
def ShowOpenPanel_(self, sender): 
    self.panel = NSOpenPanel.openPanel() 
    self.panel.setCanChooseFiles_(False) 
    self.panel.setCanChooseDirectories_(True) 
    NSLog(u'Starting OpenPanel') 
    self.panel.beginForDirectory_file_types_modelessDelegate_didEndSelector_contextInfo_(
     self.defaults.objectForKey_(u'projpath'), 
     objc.nil, 
     objc.nil, 
     self, 
     objc.selector(self.OpenPanelDidEnd_returnCode_contextInfo_, 
      signature='v:@ii'), 
     objc.nil) 
    NSLog(u'OpenPanel was started.') 

def OpenPanelDidEnd_returnCode_contextInfo_(self, panel, returnCode, context): 
    NSLog('Panel ended.') 
    if (returnCode == NSOKButton): 
     NSLog(u'User selected OK') 
     path = self.panel.filenames()[0] 
     self.defaults.setObject_forKey_(path, u'projpath') 
    del self.panel 

Die beiden wichtigsten Linien Ich bin besorgt über sind:

 objc.selector(self.OpenPanelDidEnd_returnCode_contextInfo_, 
      signature='v:@ii'), 
     objc.nil) #this is the argument that gets passed as the void pointer 

Das dritte Argument soll ein void-Zeiger sein. Da ich diese Daten nicht verwenden möchte, lasse ich sie lieber leer. Ich habe versucht, die Signatur 'v:@iv' und versuchte mit objc.NULL und Python None, und fast jede Kombination all dieser Dinge. Was ist der beste Weg, damit umzugehen?

Antwort

1

Ich denke, Sie müssen objc.selector überhaupt nicht verwenden; versuchen Sie stattdessen:

@objc.IBAction 
def ShowOpenPanel_(self, sender): 
    self.panel = NSOpenPanel.openPanel() 
    self.panel.setCanChooseFiles_(False) 
    self.panel.setCanChooseDirectories_(True) 
    NSLog(u'Starting OpenPanel') 
    self.panel.beginForDirectory_file_types_modelessDelegate_didEndSelector_contextInfo_(
     self.defaults.objectForKey_(u'projpath'), 
     objc.nil, 
     objc.nil, 
     self, 
     self.OpenPanelDidEnd_returnCode_contextInfo_, 
     objc.nil) 
    NSLog(u'OpenPanel was started.') 

Ich habe auch festgestellt, dass ich die End-of-Panel-Funktion mit PyObjCTools.AppHelper.endSheetMethod dekorieren müssen:

@PyObjCTools.AppHelper.endSheetMethod 
def OpenPanelDidEnd_returnCode_contextInfo_(self, panel, returnCode, context): 
    NSLog('Panel ended.') 
    if (returnCode == NSOKButton): 
     NSLog(u'User selected OK') 
     path = self.panel.filenames()[0] 
     self.defaults.setObject_forKey_(path, u'projpath') 
    del self.panel 

Hier ist, wie ich schreiben würde, was Sie haben:

@objc.IBAction 
def showOpenPanel_(self, sender): 
    panel = NSOpenPanel.openPanel() 
    panel.setCanChooseFiles_(False) 
    panel.setCanChooseDirectories_(True) 
    NSLog(u'Starting openPanel') 
    panel.beginForDirectory_file_types_modelessDelegate_didEndSelector_contextInfo_(
     self.defaults.objectForKey_(u'projpath'), #forDirectory 
     None, #file 
     None, #types 
     self, #modelessDelegate 
     self.openPanelDidEnd_returnCode_contextInfo_, #didEndSelector 
     None) #contextInfo 
    NSLog(u'openPanel started') 

@PyObjCTools.AppHelper.endSheetMethod 
def openPanelDidEnd_returnCode_contextInfo_(self, panel, returnCode, context): 
    NSLog(u'Panel ended') 
    if returnCode != NSOKButton: 
     return 
    NSLog(u'User selected OK') 
    path = panel.filenames()[0] 
    self.defaults.setObject_forKey_(path, u'projpath') 

Erklärung der Änderungen: Ich verwende immer None anstatt und es hat mich noch nicht vermasselt; Ich glaube nicht, dass Ihr Panel eine Eigenschaft von self sein muss, da Sie es in Ihrer Rückgabefunktion erhalten; objc Konvention ist der erste Buchstabe Ihrer Funktion in Kleinbuchstaben.

+0

Danke, ich werde es später in dieser Woche ausprobieren! –

1

Der richtige Weg, um die Platte zu öffnen ist:

@objc.IBAction 
def showOpenPanel_(self, sender): 
    panel = NSOpenPanel.openPanel() 
    panel.setCanChooseFiles_(False) 
    panel.setCanChooseDirectories_(True) 
    NSLog(u'Starting openPanel') 
    panel.beginForDirectory_file_types_modelessDelegate_didEndSelector_contextInfo_(
     self.defaults.objectForKey_(u'projpath'), #forDirectory 
     None, #file 
     None, #types 
     self, #modelessDelegate 
     'openPanelDidEnd:returnCode:contextInfo:', #didEndSelector 
     None) #contextInfo 
    NSLog(u'openPanel started') 

Code Dans wie gut funktioniert, aber IMHO meine Variante ist slighly deutlicher: Sie nicht die tatsächliche Methode kann passieren, aber den Namen der Methode, sollte heißen.

+0

Gibt es einen Vorteil, es so zu machen? Ich mag es, die tatsächliche Methode zu übergeben, weil a) es sich eher "pythonisch" anfühlt, wobei Methoden erstklassige Objekte sind, und b) Xcode den Namen der Methode für mich automatisch vervollständigt, sodass ich mich nicht um Tippfehler kümmern muss. Auch c) Ich kann eine Variable haben, um den Endselektor zu halten, wenn ich will. – Dan