尽管已设置操作,但在单击片段时显示NSSegmentedControl菜单

时间:2009-07-29 23:46:30

标签: cocoa macos controls usability

我的UI上有一个带有4个按钮的NSSegmentedControl。控件连接到一个方法,该方法将根据单击的段调用不同的方法:

- (IBAction)performActionFromClick:(id)sender {
    NSInteger selectedSegment = [sender selectedSegment];
    NSInteger clickedSegmentTag = [[sender cell] tagForSegment:selectedSegment];

    switch (clickedSegmentTag) {
            case 0: [self showNewEventWindow:nil]; break;
            case 1: [self showNewTaskWindow:nil]; break;
            case 2: [self toggleTaskSplitView:nil]; break;
            case 3: [self showGearMenu]; break;
    }
}

Segment 4在awakeFromNib方法中附加了一个菜单。当用户点击细分时,我希望此菜单下拉。此时,只有当用户点击&按住菜单。从我的在线研究来看,这是因为关联行动。

我正在解决这个问题,通过使用一些代码来获取段控件的原点并使用NSMenu的popUpContextMenu:withEvent:forView弹出上下文菜单,但这相当于hacktastic并且与标准行为相比看起来很糟糕将菜单下拉到分段控制单元下方。

有没有一种方法可以让菜单下拉,只需单击一下,而不是做hacky上下文菜单的事情?

4 个答案:

答案 0 :(得分:17)

子类NSSegmentedCell,覆盖下面的方法,并替换IB中的单元格类。 (不需要私有API)。

- (SEL)action
{
    //this allows connected menu to popup instantly (because no action is returned for menu button)
    if ([self tagForSegment:[self selectedSegment]]==0) {
        return nil;
    } else {
        return [super action];
    }
}

答案 1 :(得分:4)

这是J Hoover的答案的Swift版本和Adam Treble的模型。覆盖不像我想象的那么直观,所以这有望帮助其他人。

override var action : Selector {
        get {
            if self.menuForSegment(self.selectedSegment) != nil {
                return nil
            }
            return super.action
        }
        set {
            super.action = newValue
        }
    }

答案 2 :(得分:3)

我不确定是否有任何内置方法(虽然它确实是NSSegmentedControl API中的一个明显漏洞)。

我的建议是继续做你正在做的事情弹出上下文菜单。但是,您可以通过执行以下操作,而不是仅仅使用分段控件的原点,将其直接放在段下(如您所愿):

NSPoint menuOrigin = [segmentedControl frame].origin;
menuOrigin.x = NSMaxX([segmentedControl frame]) - [segmentedControl widthForSegment:4];
// Use menuOrigin where you _were_ just using [segmentedControl frame].origin

它并不完美或理想,但它应该完成工作并提供用户期望的外观/行为。

(另外,NSSegmentedControl 真的需要-rectForSegment:方法)

答案 3 :(得分:2)

widthForSegment:如果段自动调整大小,则返回零。如果您不关心未记录的API,则有一个rectForSegment:

  • (的NSRect)rectForSegment:(NSInteger的)段              框内:(的NSRect)帧;

但是要回答原始问题,让菜单立即弹出的更简单方法是继承NSSegmentedCell并返回0(再次,未记录)

  • (双)_menuDelayTimeForSegment:(NSInteger的)段;