2014-09-23 376 views
11

從OS X 10.10開始,大多數NSStatusItem已被棄用,以支持button屬性,該屬性由NSStatusBarButton組成。它應該像普通按鈕一樣工作,但不幸的是,NSStatusButton中的cellsetCell方法也被棄用。由於這個原因,我正在努力尋找一種方法來保持點擊之後突出顯示的按鈕(通常這個按鈕在鼠標下方突出顯示,而在鼠標上方突出顯示時不會突出顯示,我想在鼠標點亮後保持突出顯示)。NSStatusBarButton保持突出顯示

在其動作中調用[NSStatusButton setHighlighted:]不起作用,因爲它在鼠標啓動後似乎不會亮起自己。另一方面,在下一個循環中使用延遲來呼叫它,即[self performSelector: withDelay:]導致突出顯示以相當不美觀的方式閃爍。它有效,但看起來不太好。

將按鈕類型設置爲NSToggleButton可以完全消除高光,而是突出顯示奇怪的模板圖像。

那些是我能想到的唯一方法。反正有重寫這個NSButtonCell mouseUp行爲嗎?

+0

你從哪裏讀到'NSStatusItem'已被棄用? – PnotNP 2014-10-08 23:48:38

+0

@NulledPointer https://developer.apple.com/library/prerelease/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSStatusItem_Class/index.html#//apple_ref/doc/uid/TP40004118 – Luke 2014-10-10 07:38:58

+3

NSStatusItem未被棄用,它的幾種方法在10.10中已被棄用。 – ctpenrose 2015-01-06 22:42:09

回答

4

我加了一個子視圖狀態的項目,該視圖中我添加事件處理鼠標按下等,這些所謂的[ [statusItem按鈕]突出顯示:true]。事實證明,高亮:不會像高亮:做同樣的事情。

NSArray *array = [NSArray arrayWithObjects:[statusItem button], [self statusItemView], nil]; 
[[[statusItem button] superview] setSubviews:array]; 
//Highlight like so: 
[[statusItem button] highlight:true]; 

編輯:作爲酋長的這種方法不再起作用,而且也不statusItem.button.highlight = true要麼

+0

你在El Capitan找到什麼作品嗎? – 2015-09-21 05:56:12

2

TL; DR:任何NSButton實例(與NSImagetemplate=YES)內NSStatusItem財產視覺長相酷似NSStatusBarButton 。你可以控制他們的highlight屬性。

如果您想手動控制NSStatusItem的突出顯示並同時獲得使用NSStatusBarButton的所有外觀優點,則可以使用稍微不同的方法。 您可以創建自己的NSButton實例,該實例擁有完全受您控制的自己的屬性highlight。然後,您必須創建NSImage實例並將其template屬性設置爲YES。然後,您必須將此button添加到[NSStatusItem view](是,這是softly deprecated),或者甚至作爲系統創建的子視圖[NSStatusItem button]。在此之後,您必須手動使用[NSStatusItem drawStatusBarBackgroundInRect:withHighlight:]手動繪製背景NSStatusItem(這也被棄用,哦)。

通過這種方法,您可以將對NSStatusItem外觀和感覺的完全控制結合起來,並獲得按鈕圖像的自動樣式。

+1

我花了一整天的時間嘗試解決較新的API問題,但感謝您的評論,我嘗試了不贊成使用的'drawStatusBarBackgroundInRect:withHighlight:'API,並且在我看來它效果更好。我確定蘋果仍然使用不推薦使用的API作爲菜單欄圖標,因爲高亮顯示仍然存在。奇怪的是,蘋果只會在新的'NSStatusBarButton'上閃現亮點。 – iMaddin 2015-06-23 21:17:09

0

盧克的回答非常好。我只是基於此分享我的實施。

NSButton *button = [[NSButton alloc] initWithFrame:self.statusItem.button.frame]; 
button.alphaValue = 0; 
NSArray *array = @[self.statusItem.button, button]; 
self.statusItem.button.superview.subviews = array; 

[button sendActionOn:(NSLeftMouseDownMask | NSRightMouseDownMask)]; 
button.target = self; 
button.action = @selector(statusItemClicked); 
2

這個問題我自己的掙扎,我發現,覆蓋mouseDown:在類別上NSStatusBarButton作品:

#import "MUTargetClass.h" 

@implementation NSStatusBarButton (Additions) 

- (void)mouseDown:(NSEvent *)theEvent 
{ 
    // Relay CTRL+Click to perform a right click action 
    if(theEvent.modifierFlags & NSControlKeyMask) 
    { 
     [self rightMouseDown:theEvent]; 
     return; 
    } 

    // Handle highlighting 
    [self setHighlighted:YES]; 

    // Perform action on target 
    [(MUTargetClass *)self.target actionSelector:self]; 
} 

@end 

MUTargetClass可以再比如實施:

#import "NSStatusBarButton+Additions.h" 

@implementation MUTargetClass 

[…] 
    self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; 
    NSStatusBarButton *button = [self.statusItem button]; 
    [button setTarget:self]; 
[…] 

- (void)actionSelector:(id)sender 
{ 
    // Whatever behavior a click on the button should invoke 
} 

[…] 
    // Reset button's highlighting status when done 
    [[self.statusItem button] setHighlighted:NO]; 
[…] 

@end 

注意功能的CTRL +單擊該按鈕將在mouseDown:中超馳。如上所示,可以通過將事件中繼到rightMouseDown:來恢復。

一個更簡單的方法是沿目標類中的[self.target performSelector:self.action]行和目標類中的[self.statusItem setAction:@selector(actionSelector:)]行,但是ARC項目中的這個may cause a leak

編輯:這也適用於El Capitan。

+0

@xhacker:測試OS X 10.11。 – 2016-01-30 15:09:11

0

如果您安排突出顯示按鈕以便在主線程上進行後續執行,一切似乎都可以實現。這對El Capitan也有效。

if self.appPopover.shown { 
     self.appPopover.performClose(sender) 
    } else { 
     if let button = statusItem.button { 
      // set the button's highlighted property to true 
      dispatch_async(dispatch_get_main_queue(), { 
       button.highlighted = true 
      }) 

      appPopover.showRelativeToRect(button.bounds, ofView: button, preferredEdge: NSRectEdge.MinY) 
     } 
    } 

這樣做可以工作,但由於按鈕狀態從ON改變爲OFF然後再次打開,您可能會注意到有點閃爍。由於彈出顯示,OFF發生。所以,要解決這個問題,只需在突出顯示按鈕之後立即移動dispatch_async()塊內的appPopover.showRelativeToRect()調用即可。

+0

閃爍仍然出現。 – njuri 2016-04-20 13:49:34

4

這裏還有一個選項。不要設置NSStatusItemaction屬性。相反,添加本地事件監視器:

[NSEvent addLocalMonitorForEventsMatchingMask:(NSLeftMouseDown | NSRightMouseDown) 
             handler:^NSEvent *(NSEvent *event) { 
              if (event.window == self.statusItem.button.window) { 
               [self itemClicked]; 
               return nil; 
              } 
              return event; 
             }]; 

然後在-itemClicked亮點採用highlight:方法按鈕:

- (void)itemClicked { 
    [self.statusItem.button highlight:YES]; 
    // Do other stuff 
} 

要unhighlight只需調用按鈕的highlight:NO在您需要。

3

Swift 3版的Manfred Urban's答案。 在El Capitan工作。

extension NSStatusBarButton { 

    public override func mouseDown(_ event: NSEvent) { 

     if (event.modifierFlags.contains(NSControlKeyMask)) { 
      self.rightMouseDown(event) 
      return 
     } 

     self.highlight(true) 

     (self.target as? TrivialTargetClass)?.togglePopover() 
    } 
} 

如果合適,不要忘記將按鈕的高亮屬性重新設置爲false。

+0

也適用於Sierra。 – rsfinn 2017-04-21 22:46:33

-1

安東的解決方案非常完美。這是斯威夫特3:

NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown) { [weak self] event in 
    if event.window == self?.statusItem.button?.window { 
     // Your action: 
     self?.togglePopover(self?.statusItem.button) 
     return nil 
    } 

    return event 
} 

我增加了一個觀察員NSApplicationWillResignActive關閉酥料餅和設置按鈕isHighlightedfalse

相關問題