cocoa - 将 subview 带到 mouseDown 的顶部 : AND keep receiving events (for dragging)

标签 cocoa macos mouseevent nsview hittest

好吧,基本上我有一个带有一系列稍微重叠的 subview 的 View 。单击 subview 时,它会通过非常简单的两行代码移动到顶部(除其他外):

-(void)mouseDown:(NSEvent *)theEvent {
  if (_selected) { // Don't do anything this subview is already in the foreground
    return;
  }
  NSView *superview = [self superview];
  [self removeFromSuperview];
  [superview addSubview:self positioned:NSWindowAbove relativeTo:nil];
}

这工作正常,似乎是执行此操作的“正常”方式。

问题是我现在向 View 引入一些拖动逻辑,因此我需要响应 -mouseDragged:。不幸的是,由于 View 已从 View 层次结构中删除并在此过程中重新添加,因此我无法让 View 到达前台并在同一鼠标操作中拖动。它接收 mouseDown:,但从不接收 mouseDragged: 或任何后续事件。仅当我松开鼠标并再次单击 View 时,它才会拖动,因为第二次单击不会进行任何 View 层次结构杂耍。

我能做些什么来让 View 像这样移动到前台,并继续接收后续的 -mouseDragged:-mouseUp: 事件接下来是?

我开始按照在 super View 中重写 -hitTest: 的思路并拦截 mouseDown 事件,以便在实际接收之前将 View 带到前台事件。这里的问题是,在 -hitTest: 中,我如何区分我实际执行 HitTest 的事件类型?我不想将 subview 移动到前台以执行其他鼠标事件,例如 mouseMoved 等。

更新 |我实际上已经在我的 super View 中完成了此操作,但感觉就像是直接从 -hitTest: 触发事件的非常糟糕的代码味道。

-(NSView *)hitTest:(NSPoint)aPoint {
    NSView *view = [super hitTest:aPoint];
    if ([view isKindOfClass:[EDTabView class]] && ![(EDTabView *)view isActive]) {
        // Effectively simulate two mouseDown events in sequence for this special case
        [view mouseDown:nil]; // Works because I know too much about the implementation
    }
    return view;
}

有两件事感觉不对。最大的问题是我在 -hitTest: 返回之前执行操作,然后在 -hitTest: 完成后按照 AppKit 的处理方式执行操作。第二个是我没有要传递的事件,所以我传递的是零。它在这种情况下有效,因为我知道事件处理程序实际上并不处理任何事件数据,但这并不是很好。另一种方法是将整个逻辑移至 super View 中,但这里的关注点分离感觉更糟。

更新 |这个 -hitTest: hack 被破坏了......当我没有单击鼠标时,例如当我将某些东西拖到 View 顶部时,它就会被触发。仍在寻找解决此问题的好方法。

答案可以从字面上指示 View 在拖动操作期间如何离开并重新进入其 super View ,或者(也许更优雅)是将 View 移动到前台的替代方法,而不是 [view removeFromSuperview ]; [superview addSubview:view ...];.

最佳答案

好吧,我一时兴起尝试了一些不合逻辑的事情。

而不是将 View 移动到前景:

[theView removeFromSuperview];
[theSuperview addSubview:theView positioned:NSWindowAbove relativeTo:nil];

我只是删除了 removeFromSuperview 行,想知道如果您尝试向 super View 添加 View 两次,AppKit 实际上会做什么(我假设它提供了防止这种情况发生的保护)。

它可以工作,至少在 Snow Leopard 下是这样,并且它解决了很多问题。正如方法名称所暗示的那样,父 View 中已经存在的 View 不会被添加,但它确实会设置其位置,而不必先将其从父 View 中删除。

关于cocoa - 将 subview 带到 mouseDown 的顶部 : AND keep receiving events (for dragging),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4574096/

相关文章:

macos - 即使应用未运行(例如在iOS中),是否也可以将通知发送到Mountain Lion中的Notification Center?

c++ - 升级我的 mac 后编译 mpic++ 不再有效

javascript - React - 如何手动触发子组件的鼠标输入

快速创建记录并将记录添加到关系中

cocoa - 在不释放对象的情况下删除ObjectAtIndex

objective-c - 如何使用QLPreviewPanel?

android - Pushbullet API thread_id 到conversation_iden 用于短信?

javascript - react Hook useState 与数组导致缺少渲染调用

wpf - wpf中区分鼠标双击和鼠标单击

ios - 使用第一响应者而不是将方法链接到 Controller 层次结构中是否是好的应用程序设计?