似乎如果我想创建一个带有停靠图标等的非常基本的Cocoa应用程序,我将不得不使用 Xcode和GUI构建器(带有PyObjC).
我打算编写的应用程序主要关注算法和基本IO - 因此,并不主要与Apple特定的东西相关.
基本上应用程序应定期运行(例如,每3分钟一次)..通过AppleScript提取一些信息并将HTML文件写入特定目录.我想为这个应用程序添加一个Dock图标..主要是为了显示进程的"状态"(例如,如果有错误......停靠图标上会有一个红色标记).dock图标的另一个优点是我可以让它在启动时运行.
以简单的方式定义dock右键菜单的额外奖励(例如:使用Python的callables列表).
我可以在不使用Xcode或GUI构建器但只使用Emacs和Python的情况下实现这一目标吗?
安装最新的py2app,然后创建一个新目录 - cd到它 - 在其中创建一个HelloWorld.py
文件,如:
# generic Python imports import datetime import os import sched import sys import tempfile import threading import time # need PyObjC on sys.path...: for d in sys.path: if 'Extras' in d: sys.path.append(d + '/PyObjC') break # objc-related imports import objc from Foundation import * from AppKit import * from PyObjCTools import AppHelper # all stuff related to the repeating-action thesched = sched.scheduler(time.time, time.sleep) def tick(n, writer): writer(n) thesched.enter(20.0, 10, tick, (n+1, writer)) fd, name = tempfile.mkstemp('.txt', 'hello', '/tmp'); print 'writing %r' % name f = os.fdopen(fd, 'w') f.write(datetime.datetime.now().isoformat()) f.write('\n') f.close() def schedule(writer): pool = NSAutoreleasePool.alloc().init() thesched.enter(0.0, 10, tick, (1, writer)) thesched.run() # normally you'd want pool.drain() here, but since this function never # ends until end of program (thesched.run never returns since each tick # schedules a new one) that pool.drain would never execute here;-). # objc-related stuff class TheDelegate(NSObject): statusbar = None state = 'idle' def applicationDidFinishLaunching_(self, notification): statusbar = NSStatusBar.systemStatusBar() self.statusitem = statusbar.statusItemWithLength_( NSVariableStatusItemLength) self.statusitem.setHighlightMode_(1) self.statusitem.setToolTip_('Example') self.statusitem.setTitle_('Example') self.menu = NSMenu.alloc().init() menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_( 'Quit', 'terminate:', '') self.menu.addItem_(menuitem) self.statusitem.setMenu_(self.menu) def writer(self, s): self.badge.setBadgeLabel_(str(s)) if __name__ == "__main__": # prepare and set our delegate app = NSApplication.sharedApplication() delegate = TheDelegate.alloc().init() app.setDelegate_(delegate) delegate.badge = app.dockTile() delegate.writer(0) # on a separate thread, run the scheduler t = threading.Thread(target=schedule, args=(delegate.writer,)) t.setDaemon(1) t.start() # let her rip!-) AppHelper.runEventLoop()
当然,在您的真实代码中,您将每3分钟执行一次自己的定期操作(而不是像我在这里每20秒写一个临时文件),执行您自己的状态更新(而不仅仅是显示一个计数器)到目前为止写的文件数量等等,但我希望这个例子向您展示一个可行的起点.
然后在Terminal.App cd到包含此源文件的目录py2applet --make-setup HelloWorld.py
,python setup.py py2app -A -p PyObjC
.
你现在在子目录中dist
有一个目录HelloWorld.app
; open dist
并将图标拖到Dock上,你们都已经设置好了(在你自己的机器上 - 由于-A
旗帜分配给其他机器可能无法正常工作,但是如果没有它,我很难建立,可能是由于错误安装的鸡蛋文件铺设在这台机器周围;-).毫无疑问,你会想要自定义你的图标和c.
这不是你要求的"额外信用" - 这已经是很多代码了,我决定停在这里(额外的信用可能需要一个新的问题).另外,我不太确定我在这里表演的所有咒语实际上是必要的还是有用的; 如果你需要的话,文档非常适合制作一个没有Xcode的pyobjc .app,所以我在网上找到的一些示例代码和大量的反复试验一起攻击了这个.不过,我希望它有所帮助! - )