当 NSStatusBarButton 右键点击时调用动作

7

我正在寻找一种方法,以便在使用Swift的情况下检测每当右键单击NSStatusBarButton时,并调用一个动作。

我目前是这样设置的:

let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)

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")
    }
}

我考虑使用button.rightMouseDown(<#theEvent: NSEvent#>)(因为没有"alternateAction"),但很遗憾,由于我刚开始编写Mac应用程序,所以无法想出解决方案。
更新: 在寻找实现方法时,我看到一些帖子建议对NSView进行子类化,但我不知道这应该如何工作(可能是因为我刚接触编程并不知道如何进行"子类化")。尽管如此,我认为几乎每个状态栏应用程序都能在右键单击时显示矩形,因此应该有更简单的方法来实现。

注意:这个答案对我有用,尽管位掩码语法需要更新为Swift2。http://stackoverflow.com/questions/27781167/swift-right-left-click-on-nsstatusbar - Dominic
3个回答

4

你可以继承并重写mouseDown方法,但自从Mac OS X 10.10(Yosemite)以来,有一种更简单的方式:NSGestureRecognizer及其子类:

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
    }
}

3
首先感谢您的回答。不幸的是,我遇到了一个非常奇怪的问题。使用 buttonMask = 0x2 它根本没有检测到右键单击,但将掩码更改为 0x1 后,它以某种方式检测到了正常的左键单击。这对我来说似乎非常奇怪,因为我根本没有改变任何其他东西。 - Devapploper

2
我与您一样遇到了接受答案方法的相同问题:它只适用于buttonMask 0x1而不是buttonMask 0x2。常规的NSButton(但不包括NSStatusBarButtons)可以处理NSClickGestureRecognizer,因此可能这就是回答者的想法。我发现的另一个解决方案建议将NSStatusItemview设置为自己的NSView子类的实例,但是在OS X v10.10中获取或设置view已被弃用,所以我不想那样做。
我通过将NSView的自定义子类作为NSStatusItem按钮的子视图添加来解决了这个问题。我的NSView实现了-rightMouseUp:以接收右键抬起事件,然后仅将该事件传递给由我的类提供的块来处理右键单击事件。
这是我的自定义子类:
#import <Cocoa/Cocoa.h>

@interface TTRightClickDetector : NSView

@property (copy) void (^onRightMouseClicked)(NSEvent *);

@end

#import "TTRightClickDetector.h"

实现方法如下:

@implementation TTRightClickDetector

- (void)rightMouseUp:(NSEvent *)theEvent
{
    if(self.onRightMouseClicked)
    {
        self.onRightMouseClicked(theEvent);
    }
}

@end

以下是我如何使用它的方法:

self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
NSStatusBarButton *button = self.statusItem.button;
button.image = [NSImage imageNamed:@"image"];
button.action = @selector(leftMouseClicked:);

TTRightClickDetector *rightClickDetector = [[TTRightClickDetector alloc] initWithFrame:button.frame];
rightClickDetector.onRightMouseClicked = ^(NSEvent *event){
    [self rightMouseClicked];
};
[button addSubview:rightClickDetector];

0

以下是 Commanda 的答案的 Swift 版本(继承 NSView 并实现 mouseDown 方法)。

NSView 子类:

class RightMouseHandlerView: NSView {

    var onRightMouseDown: (()->())? = nil

    override func rightMouseDown(with event: NSEvent) {
        super.rightMouseDown(with: event)

        if onRightMouseDown != nil {
            onRightMouseDown!()
        }
    }
}

然后将其添加到状态栏按钮并设置代码块:

statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)

if let button = statusItem.button {
    let rmhView = RightMouseHandlerView(frame: statusItem.button!.frame)
    rmhView.rightMouseDown = {
        // Do something when right mouse down on button
    }
    button.addSubview(rmView)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接