【问题标题】:Changing the selection behaviour of NSCollectionView更改 NSCollectionView 的选择行为
【发布时间】:2015-02-18 17:57:56
【问题描述】:

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

所以,我想改变这种行为:

  • 当用户单击第二个项目时,第一个项目保持选中状态(无需按住 cmd)
  • 当用户单击选定的项目时,该项目被取消选择

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

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

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

我应该怎么做?

【问题讨论】:

  • 现在有点晚了,但我想知道:为什么不支持使用 Shift 键进行选择以扩展选择范围,就像它几乎可以在任何地方(TableViews、Finder)一样工作?

标签: cocoa nscollectionview nscollectionviewitem


【解决方案1】:

您可以尝试使用本地事件监视器拦截所有 left-mouse-down 事件。在此块中,您将确定点击是否发生在您的收藏视图上。如果确实如此,请创建一个新事件来模仿您截获的事件,但如果它不存在,则添加命令键掩码。然后,在块的末尾返回 your 事件,而不是你拦截的那个。您的集合视图的行为就像用户按下了命令键一样,即使他们没有!

我在一个非常简单的演示应用程序中快速完成了这项工作,这看起来是一种很有前途的方法 - 尽管我预计您将不得不在此过程中协商一些陷阱

- (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
    }];
}

编辑(由问题作者):

这个解决方案在很大程度上基于原始答案,所以这个答案值得称赞(随意编辑)

您还可以通过继承 NSCollectionView 类并像这样覆盖 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

【讨论】:

  • 这确实有效,但不幸的是,在鼠标事件级别拦截并将 cmd 添加到 NSCollectionView 上的所有点击会破坏我的应用程序的另一个主要功能。在我的集合视图中还有其他控件,将 cmd 添加到他们的鼠标事件会改变他们的行为。我只能找到一种方法来根据它的像素位置来区分鼠标事件。这对于整体控制来说还好,但是随着子控制的移动,我觉得不太实用。
  • 此解决方案适用于其他人,尽管他们的 NSCollectionView 中没有其他需要鼠标事件的控件。
  • 使用你建议的调整版本让它工作。希望您不介意,但我将其添加到您的答案中,因为您应得的大部分功劳。随意编辑答案,使其更简洁,对未来的人有用。
  • 出于某种原因,我从未考虑过在标准事件处理程序中调整事件 - 这是我会牢记的策略。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多