从OS X 10.10开始,大多数NSStatusItem都被弃用,而不是button
属性,该属性由NSStatusBarButton组成。它应该像普通按钮一样工作,但不幸的是,NSStatusButton中的cell
和setCell
方法也已被弃用。因此,我很难找到一种方法来保持按钮在点击后突出显示(通常按钮在鼠标按下时突出显示,在鼠标向上突出显示。我希望在鼠标按下后保持按钮突出显示)。
在其操作中调用[NSStatusButton setHighlighted:]
不起作用,因为一旦鼠标启动它似乎不会突出显示。另一方面,使用延迟在下一个循环(即[self performSelector: withDelay:]
)上调用它会导致突出显示以相当难看的方式闪烁。它有效,但看起来不太好。
将按钮类型设置为NSToggleButton
会完全删除突出显示,而是突出显示奇怪的模板图像。
这是我能想到的唯一方法。无论如何都要覆盖这个NSButtonCell mouseUp行为吗?
答案 0 :(得分:7)
这是另一个选择。不要设置NSStatusItem
的{{1}}属性。而是添加本地事件监视器:
action
然后在[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
}
即可。
答案 1 :(得分:7)
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。
答案 2 :(得分:4)
我在状态项中添加了一个子视图,在该视图中我添加了mouseDown等的事件处理程序,调用[[statusItem button] highlight:true]。事实证明setHighlighted:与亮点不同:。
NSArray *array = [NSArray arrayWithObjects:[statusItem button], [self statusItemView], nil];
[[[statusItem button] superview] setSubviews:array];
//Highlight like so:
[[statusItem button] highlight:true];
编辑:从El Capitan开始,此方法不再有效,statusItem.button.highlight = true
也不会
答案 3 :(得分:4)
我自己在这个问题上苦苦挣扎,发现在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。
答案 4 :(得分:2)
TL; DR:NSButton
内的NSImage
个template=YES
个NSStatusItem
个实例NSStatusBarButton
视觉上看起来与highlight
完全相同。您可以根据需要控制他们的NSStatusItem
属性。
如果您想手动控制NSStatusBarButton
的突出显示,同时使用NSButton
获得所有外观优势,您可以使用略有不同的方法。
您可以创建自己的highlight
实例,该实例具有完全由您控制的属性NSImage
。然后,您必须创建template
实例并将其YES
属性设置为button
。然后,您必须将此[NSStatusItem view]
添加到softly deprecated
(是,[NSStatusItem button]
),或者甚至作为系统创建的NSStatusItem
的子视图。在此之后,您必须使用[NSStatusItem drawStatusBarBackgroundInRect:withHighlight:]
手动绘制NSStatusItem
的背景(也已弃用,哦)。
通过这种方法,您可以完全控制function [Af,Bf] = rotateTwoPoints (A,B,t)
% Definition of the rotation matrix (rotation around origin (0,0) )
R=[ ...
cosd(t) -sind(t)
sind(t) cosd(t)
];
% rotation of the points A and B
Af = R*A;
Bf = R*B;
% Plot of the original line
plot(A(1),A(2),'k*', B(1),B(2),'b*');
line([A(1) B(1)],[A(2) B(2)], 'Color','r');
grid on
hold on
% Plot of the rotated line
plot(Af(1),Af(2),'g*', Bf(1),Bf(2),'r*');
line([Af(1) Bf(1)],[Af(2) Bf(2)], 'Color','b');
legend('A','B','line AB','Af','Bf','line AfBf','Location','northeastoutside');
daspect([1 1 1])
的外观和感觉,并获得按钮图像的自动样式。
答案 5 :(得分:1)
一个想法是调动isHighlighted
NSStatusBarButtonCell
并返回任意值。
https://gist.github.com/questbeat/3244601c8dc779484076
但问题在于Apple的审核小组是否允许这种方法......
答案 6 :(得分: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);
答案 7 :(得分: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()调用即可。
答案 8 :(得分:0)
这是@erikvdplas 答案的 Swift 5 版本。我在 macOS 11.4 Big Sur 上对此进行了测试。
extension NSStatusBarButton {
public override func mouseDown(with event: NSEvent) {
super.mouseDown(with: event)
self.highlight((NSApp.delegate as! YourAppDelegateClass).popover.isShown)
}
}
答案 9 :(得分:-1)
安东的解决方案非常完美。这是在Swift 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
的观察者来关闭弹出窗口,并将按钮的isHighlighted
设置为false
。