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)
}