Main cocoa app using docking station in Python but not Xcode and all these additional features

It seems that if I want to create a very basic Cocoa app with a dock icon and the like, I would use Xcode and a GUI builder (w / PyObjC ).

The app I intend to write is mostly related to algorithms and basic IO - and therefore not mainly related to Apple specific things.

Basically the application should run periodically (say every 3 minutes). Pull some information via AppleScript and write HTML files to a specific directory. I would like to add a dock icon for this application .. mainly to display the "status" of the process (eg if there is an error .. the dock icon will have a red flag on it). Another benefit of the dock icon is that I can launch it on startup.

Added bonus to easily define the dock right-click menu (ex: using Python calllists).

Can I achieve this without using Xcode or GUI constructors, but just using Emacs and Python?

+2


source to share


3 answers


Install the latest py2app then create a new directory - cd to it - a file will be created in it HelloWorld.py

like:

# 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()

      

Of course, in your real code, you will be doing your own periodic actions every 3 minutes (instead of writing a temporary file every 20 seconds as I do here), making your own status updates (and not just showing a counter of the number of files written so far), etc. and so on, but I hope this example shows you a viable starting point.



Then Terminal.App cd to the directory containing the source file py2applet --make-setup HelloWorld.py

, python setup.py py2app -A -p PyObjC

.

Now you have a subdirectory in dist

the directory HelloWorld.app

; open dist

and drag the icon to the dock and you're all set (on your own machine - spreading to other machines might not work due to the flag -A

, but I was unable to build without it, possibly due to falsely installed egg files lying around this car ;-). No doubt you will want to customize your & c icon.

It doesn't do the "extra credit" you asked for - that's a lot of code already and I decided to stop here (extra credit might require a new question). Also, I'm not entirely sure if all the spells I'm doing here are actually necessary or useful; The docs are pretty latent for building pyobjc.app without Xcode as you need to, so I hacked that along with the bits and pieces of example code I found on the net and a fair amount of trial and error. However, I hope this helps! -)

+8


source


PyObjC , which is included in Mac OS X 10.5 and 10.6, is pretty close to what you're looking for.



+2


source


Chuck is right about PyObjC.

Then you should read about this NSApplication method to change the icon.

- (void) setApplicationIconImage: (NSImage *) anImage;

For the dock menu, do the following in the application delegate. You can program NSMenu to avoid using InterfaceBuilder.

- (NSMenu *) applicationDockMenu: (NSApplication *) sender,

0


source







All Articles