How can I create a status bar item with Cocoa and Python (PyObjC)?

I have created a brand new project in XCode and have the following in my file:

from Foundation import *
from AppKit import *

class MyApplicationAppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, sender):
        NSLog("Application did finish launching.")

        statusItem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength)

However, when I launch the application no status bar item shows up. All the other code in and main.m is default.

Asked by: Joyce872 | Posted: 01-10-2021

Answer 1

The above usage of .retain() is required because the statusItem is being destroyed upon return from the applicationDidFinishLaunching() method. Bind that variable as a field in instances of MyApplicationAppDelegate using self.statusItem instead.

Here is a modified example that does not require a .xib / etc...

from Foundation import *
from AppKit import *
from PyObjCTools import AppHelper

start_time =

class MyApplicationAppDelegate(NSObject):

    state = 'idle'

    def applicationDidFinishLaunching_(self, sender):
        NSLog("Application did finish launching.")

        self.statusItem = NSStatusBar.systemStatusBar().statusItemWithLength_(NSVariableStatusItemLength)
        self.statusItem.setTitle_(u"Hello World")

        # Get the timer going
        self.timer = NSTimer.alloc().initWithFireDate_interval_target_selector_userInfo_repeats_(start_time, 5.0, self, 'tick:', None, True)
        NSRunLoop.currentRunLoop().addTimer_forMode_(self.timer, NSDefaultRunLoopMode)

    def sync_(self, notification):
        print "sync"

    def tick_(self, notification):
        print self.state

if __name__ == "__main__":
    app = NSApplication.sharedApplication()
    delegate = MyApplicationAppDelegate.alloc().init()

Answered by: Emma166 | Posted: 02-11-2021

Answer 2

I had to do this to make it work:

  1. Open MainMenu.xib. Make sure the class of the app delegate is MyApplicationAppDelegate. I'm not sure if you will have to do this, but I did. It was wrong and so the app delegate never got called in the first place.

  2. Add statusItem.retain() because it gets autoreleased right away.

Answered by: Kelvin382 | Posted: 02-11-2021

Similar questions

Still can't find your answer? Check out these communities...

PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python