简体   繁体   中英

Problem With openPanelDidEnd in PyObjC in 10.6

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>

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.

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 (ie, 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'))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM