Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 单击浏览NSView_Objective C_Cocoa - Fatal编程技术网

Objective c 单击浏览NSView

Objective c 单击浏览NSView,objective-c,cocoa,Objective C,Cocoa,我有一个包含多个子视图的NSView。其中一个子视图是透明的,并在顶部分层 我需要能够通过此视图向下单击到下面的子视图(以便下面的视图获得第一响应者状态),但所有鼠标事件都会卡在顶部视图上(alpha为1,因为我在其中绘制内容-因此它应该只通过透明区域单击) 事实上,我认为这会起作用,因为通常情况下是这样的。有什么问题吗?将透明视图放在它自己的子窗口中。我用这个代码片段绕过了这个问题 - (NSView *)findNextSiblingBelowEventLocation:(NSEvent *

我有一个包含多个子视图的
NSView
。其中一个子视图是透明的,并在顶部分层

我需要能够通过此视图向下单击到下面的子视图(以便下面的视图获得第一响应者状态),但所有鼠标事件都会卡在顶部视图上(alpha为
1
,因为我在其中绘制内容-因此它应该只通过透明区域单击)


事实上,我认为这会起作用,因为通常情况下是这样的。有什么问题吗?

将透明视图放在它自己的子窗口中。

我用这个代码片段绕过了这个问题

- (NSView *)findNextSiblingBelowEventLocation:(NSEvent *)theEvent {
  // Translate the event location to view coordinates
  NSPoint location = [theEvent locationInWindow];
  NSPoint convertedLocation = [self convertPointFromBase:location];

  // Find next view below self
  NSArray *siblings = [[self superview] subviews];
  NSView *viewBelow = nil;
  for (NSView *view in siblings) {
    if (view != self) {
      NSView *hitView = [view hitTest:convertedLocation];
      if (hitView != nil) {
        viewBelow = hitView;
      }
    }
  }
  return viewBelow;
}

- (void)mouseDown:(NSEvent *)theEvent {
  NSView *viewBelow = [self findNextSiblingBelowEventLocation:theEvent];
  if (viewBelow) {
    [[self window] makeFirstResponder:viewBelow];
  }
  [super mouseDown:theEvent];
}

这是另一种方法。它不需要创建新的窗口对象,并且比上面的findNextSiblingBelowEventLocation:方法更简单(可能更高效)

- (NSView *)hitTest:(NSPoint)aPoint
{
    // pass-through events that don't hit one of the visible subviews
    for (NSView *subView in [self subviews]) {
        if (![subView isHidden] && [subView hitTest:aPoint])
            return subView;
    }

    return nil;
}

以下是Swift 5的版本:

public override func hitTest(uu点:NSPoint)->NSView?{
//传递未命中其中一个可见子视图的事件
返回子视图。中的第一个{子视图
!subview.ishiden&&nil!=subview.hitTest(点)
}
}

以下是Swift 5的版本:


视图
-isOpaque
NO
,因为通过窗口的透明部分解析命中是窗口管理器的固有特性。您上面所做的工作是没有必要的。哦,我刚刚意识到实际上有一个方法
-addChildWindow:
可以同步窗口!抱歉,我当时认为我必须手动进行同步。我尝试使用这种方法,但它有更多的缺点,即使用
-findNextSiblingBelowEventLocation:
解决方法,因为窗口实际上没有绑定到
NSView
,因此在视图不可见时也会绘制它,当视图位于滚动视图内时,它不起作用。这是解决一个小问题的一种非常严厉的方法
public override func mouseDown(with event: NSEvent) {
    // Translate the event location to view coordinates
    let convertedLocation = self.convertFromBacking(event.locationInWindow)

    if let viewBelow = self
        .superview?
        .subviews // Find next view below self
        .lazy
        .compactMap({ $0.hitTest(convertedLocation) })
        .first
    {
        self.window?.makeFirstResponder(viewBelow)
    }

    super.mouseDown(with: event)
}