10.6中PyObjC的openPanelDidEnd问题
下面这段代码在 OS X 10.5 上运行得很好,但在 10.6 上却出错了:
@IBAction
def addButton_(self, sender):
panel = NSOpenPanel.openPanel()
panel.setCanChooseDirectories_(YES)
panel.setAllowsMultipleSelection_(YES)
try:
panel.beginSheetForDirectory_file_modalForWindow_modalDelegate_didEndSelector_contextInfo_(self.directory, None, NSApp().mainWindow(), self, 'openPanelDidEnd:panel:returnCode:contextInfo:', None)
except:
pass
@AppHelper.endSheetMethod
def openPanelDidEnd_panel_returnCode_contextInfo_(self, panel, returnCode, contextInfo):
我遇到的错误是:
objc.BadPrototypeError: Python signature doesn't match implied Objective-C signature for <unbound selector openPanelDidEnd:panel:returnCode:contextInfo: of controller at 0x6166a70>
2 个回答
正如elv所提到的,beginSheetForDirectory:file:modalForWindow:modalDelegate:didEndSelector:contextInfo:
这个方法在10.6版本中已经不再推荐使用了,新的方法是beginSheetModalForWindow:completionHandler:
。在随Snow Leopard发布的PyObjC版本中,这个方法没有相关的元数据,但现在已经添加了,你可以自己更新相应的文件,以便使用这个方法。打开这个路径:/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport,然后找到以下内容:
<class name='NSSavePanel'>
在这个内容里面,添加以下内容:
<method selector='beginSheetModalForWindow:completionHandler:'>
<arg index='1' block='true' >
<retval type='v' />
<arg type='i' type64='q' />
</arg>
</method>
<method selector='beginWithCompletionHandler:'>
<arg index='0' block='true' >
<retval type='v' />
<arg type='i' type64='q' />
</arg>
</method>
这就是Python那边需要的元数据,以便能够正确获取和返回对象给Objective-C。你可以传递任何可调用的函数作为完成处理器,只要它的格式正确(也就是说,接受一个整数参数并且不返回任何东西)。举个例子:
def showOpenPanel_(self, sender):
openPanel = NSOpenPanel.openPanel()
def openPanelDidClose_(result):
if result == NSFileHandlingPanelOKButton:
openPanel.orderOut_(self)
image = NSImage.alloc().initWithContentsOfFile_(openPanel.filename())
self.imgView.setImage_(image)
openPanel.setAllowedFileTypes_(NSImage.imageFileTypes())
openPanel.beginSheetModalForWindow_completionHandler_(self.imgView.window(),
objc.selector(openPanelDidClose_, argumentTypes='l'))
在10.6版本中,beginSheetForDirectory:file:modalForWindow:modalDelegate:didEndSelector:这个方法已经被淘汰了。你可以在这里查看详细信息:http://developer.apple.com/library/mac/#documentation/cocoa/reference/ApplicationKit/Classes/NSOpenPanel_Class/DeprecationAppendix/AppendixADeprecatedAPI.html
我在解决同样的问题时遇到困难,因为PyObjC没有块签名,具体可以参考这个链接:http://pyobjc.sourceforge.net/documentation/pyobjc-core/blocks.html。对于beginSheetModalForWindow:completionHandler:这个方法,你只能使用runModal。
我的解决方案是:
panel = NSOpenPanel.openPanel()
panel.setCanChooseDirectories_(NO)
panel.setAllowsMultipleSelection_(NO)
panel.setAllowedFileTypes_(self.filetypes)
panel.setDirectoryURL_(os.getcwd())
ret = panel.runModal()
if ret:
print panel.URL()
panel.URL()会返回用户选择的文件。