2

I'm trying to get a dynamic label for a menu item in this. I've written the entire app in Python but honestly with how much NSMenuItem looks, I might as well rewrite it in Objc...

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

class MyApp(NSApplication):

    def finishLaunching(self):
        # Make statusbar item
        statusbar = NSStatusBar.systemStatusBar()
        self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength)
        self.icon = NSImage.alloc().initByReferencingFile_('icon.png')
        self.icon.setScalesWhenResized_(True)
        self.icon.setSize_((20, 20))
        self.statusitem.setImage_(self.icon)

        #make the menu
        self.menubarMenu = NSMenu.alloc().init()

        self.menuItem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Click Me', 'clicked:', '')
        self.menubarMenu.addItem_(self.menuItem)

        self.quit = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Quit', 'terminate:', '')
        self.menubarMenu.addItem_(self.quit)

        #add menu to statusitem
        self.statusitem.setMenu_(self.menubarMenu)
        self.statusitem.setToolTip_('My App')

    def clicked_(self, notification):
        NSLog('clicked!')

if __name__ == "__main__":
    app = MyApp.sharedApplication()
    AppHelper.runEventLoop()
Matthew
  • 837
  • 3
  • 18
  • 33
  • 1
    What's the bug? You haven't indicated where it doesn't work. Is something supposed to happen somewhere when you do something, that's not? – blakev Aug 25 '13 at 17:23
  • It's not so much that it doesn't work but I'm not sure how to implement that I'd like a dynamic label in for an item. Something I can modify after the status bar as been created. – Matthew Aug 25 '13 at 17:26
  • You can either remove the MenuItem and re-add the changed value while the menu is closed, or look for a "redraw" type function on NSMenuItem and NSMenuItem.alloc() ~ an application is like a canvas, the only way you can change what you see is by redrawing part or the whole thing. I don't think you can just change the label, but if you made your own redraw function you could pass labels in that would reflect what you want them to read at that time. – blakev Aug 25 '13 at 17:35

1 Answers1

2

Did you try setTitle_?

def clicked_(self, notification):
    self.menuItem.setTitle_("Clicked!")

or with a timer:

def finishLaunching(self):
    # ...

    self.timer = NSTimer.alloc().initWithFireDate_interval_target_selector_userInfo_repeats_(NSDate.date(), 1.0, self, 'tick:', None, True)
    NSRunLoop.currentRunLoop().addTimer_forMode_(self.timer, NSDefaultRunLoopMode)
    self.timer.fire()


def tick_(self, arg):
    self.menuItem.setTitle_("Tick %d!" % int(time.time()))

For live updates you probably need JGMenuWindow (SO: How to update NSMenu while it's open?)

Community
  • 1
  • 1
chlunde
  • 1,547
  • 11
  • 11
  • Fantastic! Exactly what I needed. How would I go about added a submenu? I tried adding a menuitem with setSubmenu_ but it wouldn't work.. – Matthew Sep 06 '13 at 04:15