0

我需要检测用户何时在停靠菜单中按下“退出”。

我的应用程序实际上只是 Web 界面后端服务器的启动器。我通过手动等待启动的进程结束(使用轮询和睡眠)将其保留在停靠菜单中。活动监视器显示它没有响应,因此我添加了一个本机函数来处理诸如“触摸”之类的事件。无响应标志现在消失了,但用户无法退出此应用程序(我猜是因为本机函数处理事件)。

我使用 ctypes 来访问该本地函数。

TVB = subprocess.popen(args)
coreFoundation = cdll.LoadLibrary('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation')

CFRunLoopRunInMode = coreFoundation.CFRunLoopRunInMode                  # the native function
CFRunLoopRunInMode.restype = c_int32                                    # its return type
CFRunLoopRunInMode.argtypes = [ c_void_p, c_double, c_bool ]            # its arguments types

defaultMode = c_void_p.in_dll(coreFoundation, u'kCFRunLoopDefaultMode') # the default mode to process events
sleepTime = c_double(5)                                                 # the duration to process the events
retAfterSourceHandled = c_bool(0)                                       # do NOT return after processing

while not TVB.poll():                                                   # keep alive as long as TVB is alive
    CFRunLoopRunInMode(defaultMode, sleepTime, retAfterSourceHandled)
    sleep(5)
    #detect 'quit' here and stop TVB, then quit

我还将考虑其他解决方案CFRunLoopRunInMode......类似的东西processNextEvent()是理想的。

4

1 回答 1

2

此问题的一个可能解决方案是使用PyObjC和自定义UIApplicationDelegate实现。

    import AppKit
    import Foundation
    from PyObjCTools import AppHelper

    class ApplicationDelegate(Foundation.NSObject):
        """ MAC OS UI specific Delegate class """

        def applicationDidFinishLaunching_(self, notification):
            """ Here you could register a timer to pull your sub-processes, for example. """
            pass

        def applicationWillTerminate_(self, notification):
            """ This is the hook you get for when the user clicks QUIT in dock """
            pass

    app = AppKit.NSApplication.sharedApplication()
    delegate = ApplicationDelegate.alloc().init()
    app.setDelegate_(delegate)
    AppHelper.runEventLoop()

最后,PyObjC 与您尝试的 ctypes 加载没有太大区别,但它有一些帮助方法(如 AppKit.NSRunLoop.currentRunLoop() 或 AppHelper.stopEventLoop())可以使 python 代码更清晰。

对于这个解决方案,我假设有一个 Python 项目进一步打包以使用 py2app 进行部署。我使用了 pyObjc 2.3 版(在 Mac OS x 10.7.5 上的 Python 2.7 中使用 easy_install 安装)。

于 2013-10-01T12:25:54.897 回答