NSPopUpButton
のサブクラスを作成し、mouseDown
/mouseUp
イベントを上書きします。
の実装を呼び出す前に、マウスがまだ押されている場合のみ、mouseDown
イベントの遅延が発生します。
は、ボタンのtarget
/action
を焼成前mouseUp
イベントがnil
にselectedMenuItem
を設定する(したがってselectedMenuItemIndex
が-1
になります)があります。
唯一の他の問題は、将来のクリックに対してマウスが押された瞬間に1回のクリックのタイマーが起動する急速なクリックを処理することです。 NSTimer
を使用して無効にする代わりに、私はmouseDown
イベントの簡単なカウンタを選択し、カウンタが変更された場合には救済します。ここで
が、私は私のサブクラスで使用しているコードです:
// MyClickAndHoldPopUpButton.h
@interface MyClickAndHoldPopUpButton : NSPopUpButton
@end
// MyClickAndHoldPopUpButton.m
@interface MyClickAndHoldPopUpButton()
@property BOOL mouseIsDown;
@property BOOL menuWasShownForLastMouseDown;
@property int mouseDownUniquenessCounter;
@end
@implementation MyClickAndHoldPopUpButton
// highlight the button immediately but wait a moment before calling the super method (which will show our popup menu) if the mouse comes up
// in that moment, don't tell the super method about the mousedown at all.
- (void)mouseDown:(NSEvent *)theEvent
{
self.mouseIsDown = YES;
self.menuWasShownForLastMouseDown = NO;
self.mouseDownUniquenessCounter++;
int mouseDownUniquenessCounterCopy = self.mouseDownUniquenessCounter;
[self highlight:YES];
float delayInSeconds = [NSEvent doubleClickInterval];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if (self.mouseIsDown && mouseDownUniquenessCounterCopy == self.mouseDownUniquenessCounter) {
self.menuWasShownForLastMouseDown = YES;
[super mouseDown:theEvent];
}
});
}
// if the mouse was down for a short enough period to avoid showing a popup menu, fire our target/action with no selected menu item, then
// remove the button highlight.
- (void)mouseUp:(NSEvent *)theEvent
{
self.mouseIsDown = NO;
if (!self.menuWasShownForLastMouseDown) {
[self selectItem:nil];
[self sendAction:self.action to:self.target];
}
[self highlight:NO];
}
@end
NSSegmentedControlの奥行きを設定できないのは残念です。大きなボタンに貼り付けられたメニューが必要です。 – zrxq
完璧に作業しました!ありがとう! – Alex
素敵なトリックで、IBの周りを少し遊んで、このような本当にエレガントなコントロールを得ることができます。 –