Nsstatusitem in Nsstatusbar, Action Selector Method Not Responding

NSMenu and NSStatusItem action wont work together


"If the status item has a menu set, the action is not sent to the target when the status item is clicked; instead, the click causes the menu to appear."- apple dev NSStatusItem.action

refresh NSMenuItem on click/open of NSStatusItem

Keep a reference to the created NSMenuItem in your app delegate and update its state (assuming you use the item only in a single menu).

class AppDelegate: NSApplicationDelegate {

var fooMenuItem: NSMenuItem?

}

func createStatusBarItem() {
...
let enableDisableMenuItem = NSMenuItem(title: "Enabled", action: #selector(toggleAdvancedMouseHandlingObjc), keyEquivalent: "e")
self.fooMenuItem = enableDisableMenuItem
...
}

@objc func toggleAdvancedMouseHandlingObjc() {
if sHandler.isAdvancedMouseHandlingEnabled() {
sHandler.disableAdvancedMouseHandling()
} else {
sHandler.enableAdvancedMouseHandling()
}

self.fooMenuItem.state = sHandler.isAdvancedMouseHandlingEnabled() ? NSControl.StateValue.on : NSControl.StateValue.off
}

How to bind selector to method inside NSObject

Setting the button's action is only one half of what you need to do. You also need to specify a target. Add

 self.item.button?.target = self 

and I believe you will get the result you are looking for.

What's happening is action specifies the selector to invoke and target specifies the object on which to invoke it.

Action of StatusItem not working in Swift

If the button is showing up and nothing is happening when you click it, it looks to me like you need to make sure you're setting your button's target to your App instance. E.g.:

button.target = self

Otherwise the action is only followed up the responder chain.

NSMenuItem with action added to NSStatusBar is grayed out when the selected function is moved to other class

The solution was to manually set the target property to self as @vadian and @red_menace helped me discover in the comments of the question.

The working code looks like this:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBarItemController: StatusBarItemController?

func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
statusBarItemController = StatusBarItemController()
}

func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}

}
import Cocoa

class StatusBarItemController: NSObject {
let statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)

override init() {
super.init()
if let button = statusBarItem.button {
button.image = NSImage(named: NSImage.Name("trayIcon"))
}
constructMenu()
}

func constructMenu() {
if let button = statusBarItem.button {
button.image = NSImage(named: NSImage.Name("trayIcon"))
}
let menu = NSMenu()

let fromTheWindowsItem = NSMenuItem(
title: "From the windows...",
action: #selector(StatusBarItemController.printToTheWalls(_:)),
keyEquivalent: ""
)
fromTheWindowsItem.target = self
menu.addItem(fromTheWindowsItem)
menu.addItem(NSMenuItem.separator())
menu.addItem(NSMenuItem(
title: "Quit",
action: #selector(NSApplication.terminate(_:)),
keyEquivalent: "q"
))

statusBarItem.menu = menu
}

@objc func printToTheWalls(_ sender: NSMenuItem) {
print("To the Walls!")
}
}

Call Action when NSStatusBarButton is right-clicked

You can subclass and override the mouseDown method, but since Mac OS X 10.10 (Yosemite), there has been an easier way: NSGestureRecognizer and its subclasses:

func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
if let button = statusItem.button {
button.image = NSImage(named: "myImage")
button.alternateImage = NSImage(named: "myImage")
button.action = Selector("myAction")

// Add right click functionality
let gesture = NSClickGestureRecognizer()
gesture.buttonMask = 0x2 // right mouse
gesture.target = self
gesture.action = "myRightClickAction:"
button.addGestureRecognizer(gesture)
}
}

func myRightClickAction(sender: NSGestureRecognizer) {
if let button = sender.view as? NSButton {
// Handle your right click event here
}
}

How can I call a function/action when a statusItem is clicked?

I was able to reach an implementation shown below, using the new NSStatusBarButton visual representation of an NSStatusBarItem. In this example, my .xib file has the NSPopover element already connected to a view, which isn't shown here.

@IBOutlet weak var myPopover: NSPopover!
var statusBar: NSStatusItem!
var popoverIsOpen = false

@IBAction func togglePopover(sender: AnyObject) {
if !(popoverIsOpen) {
myPopover.showRelativeToRect(sender.bounds, ofView: statusBar.button, preferredEdge: NSRectEdge(3))
popoverIsOpen = true
}
else {
myPopover.close()
popoverIsOpen = false
}
}

func applicationDidFinishLaunching(aNotification: NSNotification?) {
//initialize menu bar icon
statusBar = NSStatusBar.systemStatusBar().statusItemWithLength(CGFloat(48))
statusBar.button.title = "Your App Title"
statusBar.button.appearsDisabled = false
statusBar.button.action = Selector("togglePopover:")
statusBar.button.target = self
}


Related Topics



Leave a reply



Submit