如何在PyObjC选择器中表示void指针?

时间:2009-05-10 19:39:38

标签: python objective-c macos pyobjc void-pointers

我想将NSOpenPanel用于我正在设计的应用程序。这是我到目前为止所做的:

@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

我关注的主要两条线是:

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

第三个参数应该是一个void指针。由于我不打算使用这些数据,我宁愿把它留空。我尝试过制作签名'v:@iv'并尝试使用objc.NULL和python的None,以及几乎所有这些内容的组合。处理这个问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

我认为您根本不需要使用objc.selector;试试这个:

@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.')

我还发现我需要使用PyObjCTools.AppHelper.endSheetMethod来装饰面板结束功能:

@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

以下是我如何写你所拥有的:

@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')

变化说明:我总是使用None而不是objc.nil而且它还没有搞砸我;我不认为你的面板需要成为self的属性,因为你在返回函数中得到它; objc约定是以小写形式包含函数的第一个字母。

答案 1 :(得分:1)

打开面板的正确方法是:

@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')

Dan的代码也可以,但恕我直言我的变体更清晰:你没有传递实际的方法,而是应该调用的方法的名称。