I am using Pyobjc to create a NSStatusItem. When it is clicked, I am showing an NSPopOver. This is working fine. However, my requirement is to show the popover as soon as the application starts without any action by the user. Calling the callback directly in finishLaunching is not working. Is there any way to achieve this? It will be good enough even if can just simulate the click on NSStatusView.
class TestApp(NSApplication):
def finishLaunching(self):
# Make statusbar item
statusbar = NSStatusBar.systemStatusBar()
self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength)
self.statusitem.setTarget_(self)
self.statusitem.setAction_('statusItemClicked:')
self.icon = NSImage.alloc().initByReferencingFile_('app-icon.png')
self.icon.setScalesWhenResized_(True)
self.icon.setSize_((20, 20))
self.statusitem.setImage_(self.icon)
self.statusitem.setHighlightMode_(1)
# self.statusItemClicked_(None)
def statusItemClicked_(self, notification):
self.viewController = SimpleXibDemoController.alloc().initWithWindowNibName_("Login")
# Show the window
self.viewController.showWindow_(self.viewController)
rect = self.statusitem.valueForKey_('button').frame()
self.viewController.popover.showRelativeToRect_ofView_preferredEdge_(rect, self.statusitem.valueForKey_('button'), NSMaxYEdge)
I finally got a somewhat sketchy solution. I have a method which positions the popover like so:
- (IBAction)showPopover:(id)sender {
[popover showRelativeToRect:self.statusItemView.bounds ofView:self.statusItemView preferredEdge:NSMinYEdge];
}
In applicationDidFinishLaunching, or finishLaunching in your case, instead of calling the method directly I called it with performSelector instead:
[self performSelector:@selector(showPopover:) withObject:self afterDelay:0];
Even setting the delay to 0 works, which I do not know why, and it now positions the popover correctly.
Edit: This seems to only work situationally. Even by creating a view controller and calling it from viewDidAppear, the popover only gets positioned half of the time.
Edit 2: I added a window controller to the status item's window, and overrode windowDidLoad. However as it turned out, the window is loaded before I can even set the controller's window so windowDidLoad is not called.
You have to wait until the view appears to present the NSPopover
. Override viewDidAppear
in your NSViewController
subclass and present it there. (Or override loadView
if your minimum deployment target is less than OS X Yosemite.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With