问题
The following code which worked fine under OS X 10.5 now fails on 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):
The error I get is:
objc.BadPrototypeError: Python signature doesn't match implied Objective-C signature for <unbound selector openPanelDidEnd:panel:returnCode:contextInfo: of controller at 0x6166a70>
回答1:
beginSheetForDirectory:file:modalForWindow:modalDelegate:didEndSelector:contextInfo: has been deprecated in 10.6: http://developer.apple.com/library/mac/#documentation/cocoa/reference/ApplicationKit/Classes/NSOpenPanel_Class/DeprecationAppendix/AppendixADeprecatedAPI.html
struggling on the same problem cause PyObjC has no block signature http://pyobjc.sourceforge.net/documentation/pyobjc-core/blocks.html for beginSheetModalForWindow:completionHandler: and you can only use runModal
my solution:
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() returns the user selection.
回答2:
As elv notes, beginSheetForDirectory:file:modalForWindow:modalDelegate:didEndSelector:contextInfo:
has been deprecated in 10.6, and the new method to use is beginSheetModalForWindow:completionHandler:
There's no metadata for this method in the version of PyObjC that shipped with Snow Leopard, but it has since been added, and you can update the appropriate file yourself so that you can use this method. Open /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport and find the element:
<class name='NSSavePanel'>
inside this, add the following:
<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>
This is the metadata that the Python side needs in order to get and return the correct types of objects to Objective-C. You can pass any callable for the completion handler, as long as it has the correct signature (i.e., takes an integer argument and returns nothing). An example:
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'))
来源:https://stackoverflow.com/questions/3809340/problem-with-openpaneldidend-in-pyobjc-in-10-6