更改 NSCollectionView 的选择行为

Changing the selection behaviour of NSCollectionView

在我的 Mac 应用程序中,我有一个启用了多个 select 的 NSCollectionView。在我的应用程序中,能够 select 多个项目是常态,并且必须在单击 select 多个项目的同时按 cmd 让一些用户感到沮丧,而且大多数人没有意识到他们可以做到这一点 (我收到很多功能请求要求多 select).

所以,我想改变行为以便:

我试过在我自己的 NSCollectionViewItem 子类上覆盖 setSelected,如下所示:

-(void)setSelected:(BOOL)flag
{
    [super setSelected:flag];
    [(MyView*)[self view] setSelected: flag];
    [(MyView*)[self view] setNeedsDisplay:YES];
}

需要调用 super setSelected 以确保集合视图正常运行,但它似乎也是造成默认行为的原因。

我应该怎么做?

您可以尝试使用本地事件监视器拦截所有 鼠标左键按下 事件。在此块中,您将计算出点击是否发生在您的集合视图上。如果是这样,请创建一个新事件来模仿您拦截的事件,但如果它不存在,请添加命令键掩码。然后,在块的末尾 return 你的 事件而不是你拦截的事件。您的集合视图将表现得好像用户按下了命令键,即使他们没有!

我在一个非常简单的演示应用程序中快速完成了这个,它看起来是一个很有前途的方法 - 虽然我希望你必须协商一些 gotchas方式。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {


    [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskFromType(NSLeftMouseDown) 
            handler:^NSEvent *(NSEvent *originalEvent) {

        // Did this left down event occur on your collection view? 
        // If it did add in the command key

        NSEvent *newEvent =
            [NSEvent
                mouseEventWithType: NSLeftMouseDown
                location: originalEvent.locationInWindow
                modifierFlags: NSCommandKeyMask // I'm assuming it's not already present
                timestamp: originalEvent.timestamp
                windowNumber: originalEvent.windowNumber
                context: originalEvent.context
                eventNumber: originalEvent.eventNumber
                clickCount: originalEvent.clickCount
                pressure:0];

        return newEvent; // or originalEvent if it's nothing to do with your collection view
    }];
}

编辑(由问题作者):

此解决方案在很大程度上基于原始答案,因此该答案值得信赖(随意编辑)

您还可以通过子classing NSCollectionView class 并像这样覆盖 mousedown 来拦截鼠标事件:

@implementation MyCollectionView

-(void) mouseDown:(NSEvent *)originalEvent {

    NSEvent *mouseEventWithCmd =
        [NSEvent
            mouseEventWithType: originalEvent.type
            location: originalEvent.locationInWindow
            modifierFlags: NSCommandKeyMask
            timestamp: originalEvent.timestamp
            windowNumber: originalEvent.windowNumber
            context: originalEvent.context
            eventNumber: originalEvent.eventNumber
            clickCount: originalEvent.clickCount
            pressure: originalEvent.pressure];

    [super mouseDown: mouseEventWithCmd];
}

@end