拖动时未在嵌套视图上调用 NSView mouseEntered - 黑客攻击是唯一的选择吗?
NSView mouseEntered not called on nested view whilst dragging - Is hacking the only option?
如果我不拖动鼠标,我有一个带有嵌套 NSView 的 NSView 使用 NSTracking 区域在所有子视图上触发事件...很好。
但是当我从父 NSView 拖动到子 NSView 上时,鼠标事件没有被触发,然后我让它们响应事件的唯一方法是通过黑客攻击,感觉很脏。
NSView *hit = [self findViewUnderPoint:loc];
if (hit != nil)
{
if (hit != last)
{
[last mouseExited:event]; // This looks terrible to me
} else {
[hit mouseEntered:event]; // This looks terrible to me
}
last = hit;
}
如果你把上面的代码注释掉,子视图的事件不会被触发,如果你把它留在里面它们是......但我是直接调用它们。
我上传了一个视频,先向您展示它是如何工作的,然后是拖动(用我的技巧)- 我还包括了我的源代码。
我很想 "the right way" 完成这件事
https://www.dropbox.com/s/b6ps8tz0jvg2gwy/Designable.zip?dl=0
也许这个问题可能与您的订阅方式有关class。
您是否在覆盖的 class 方法中调用超级方法?
您是从 NSView 继承特定的预先存在的控件还是立即继承?
您在 XCode 中收到任何警告吗?
编辑:
你好,
我正在玩一些像你这样的简化的东西。
您是否查看了 CableView 子程序中的 hitTest: overrideclass?也许它应该 return 不同:
return 自我 == hitView ? self:nil;
这是我对视图子class 的愚蠢实现,它在拖动时绘制向导:
#import "MYSimpleScratchPad.h"
@implementation MYSimpleScratchPad
{
NSPoint start;
NSPoint finish;
BOOL dragging;
}
- (instancetype)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self) {
_path = [NSBezierPath bezierPath];
dragging = NO;
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
[[NSColor redColor] set];
[_path removeAllPoints];
if (dragging) {
[_path setLineWidth:5.0];
[_path setLineCapStyle:NSRoundLineCapStyle];
[_path moveToPoint:start];
[_path lineToPoint:finish];
[_path stroke];
}
}
- (void)mouseDown:(NSEvent *)event {
start = [event locationInWindow];
NSRect theFrame = [self frame];
start.x -= theFrame.origin.x;
start.y -= theFrame.origin.y;
_path = [NSBezierPath bezierPath];
}
- (void)mouseDragged:(NSEvent *)event {
finish = [event locationInWindow];
NSRect theFrame = [self frame];
finish.x -= theFrame.origin.x;
finish.y -= theFrame.origin.y;
dragging = YES;
[self setNeedsDisplay:YES];
}
- (void)mouseUp:(NSEvent *)event {
start = NSMakePoint(0.0, 0.0);
finish = NSMakePoint(0.0, 0.0);
dragging = NO;
[self setNeedsDisplay:YES];
}
- (NSView *)hitTest:(NSPoint)point {
NSView *hitView = [super hitTest:point];
return self == hitView ? self:nil;
}
@end
如Handling Mouse Dragging Operations中所述,有两种实现拖动的方法。您的解决方案使应用程序的正常事件循环短路,您必须调用 mouseEntered:
和 mouseExited:
。如果您不想这样做,请实施具有其他缺点的三种方法。
如果我不拖动鼠标,我有一个带有嵌套 NSView 的 NSView 使用 NSTracking 区域在所有子视图上触发事件...很好。
但是当我从父 NSView 拖动到子 NSView 上时,鼠标事件没有被触发,然后我让它们响应事件的唯一方法是通过黑客攻击,感觉很脏。
NSView *hit = [self findViewUnderPoint:loc];
if (hit != nil)
{
if (hit != last)
{
[last mouseExited:event]; // This looks terrible to me
} else {
[hit mouseEntered:event]; // This looks terrible to me
}
last = hit;
}
如果你把上面的代码注释掉,子视图的事件不会被触发,如果你把它留在里面它们是......但我是直接调用它们。
我上传了一个视频,先向您展示它是如何工作的,然后是拖动(用我的技巧)- 我还包括了我的源代码。
我很想 "the right way" 完成这件事
https://www.dropbox.com/s/b6ps8tz0jvg2gwy/Designable.zip?dl=0
也许这个问题可能与您的订阅方式有关class。 您是否在覆盖的 class 方法中调用超级方法? 您是从 NSView 继承特定的预先存在的控件还是立即继承? 您在 XCode 中收到任何警告吗?
编辑:
你好, 我正在玩一些像你这样的简化的东西。
您是否查看了 CableView 子程序中的 hitTest: overrideclass?也许它应该 return 不同: return 自我 == hitView ? self:nil;
这是我对视图子class 的愚蠢实现,它在拖动时绘制向导:
#import "MYSimpleScratchPad.h"
@implementation MYSimpleScratchPad
{
NSPoint start;
NSPoint finish;
BOOL dragging;
}
- (instancetype)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self) {
_path = [NSBezierPath bezierPath];
dragging = NO;
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
[[NSColor redColor] set];
[_path removeAllPoints];
if (dragging) {
[_path setLineWidth:5.0];
[_path setLineCapStyle:NSRoundLineCapStyle];
[_path moveToPoint:start];
[_path lineToPoint:finish];
[_path stroke];
}
}
- (void)mouseDown:(NSEvent *)event {
start = [event locationInWindow];
NSRect theFrame = [self frame];
start.x -= theFrame.origin.x;
start.y -= theFrame.origin.y;
_path = [NSBezierPath bezierPath];
}
- (void)mouseDragged:(NSEvent *)event {
finish = [event locationInWindow];
NSRect theFrame = [self frame];
finish.x -= theFrame.origin.x;
finish.y -= theFrame.origin.y;
dragging = YES;
[self setNeedsDisplay:YES];
}
- (void)mouseUp:(NSEvent *)event {
start = NSMakePoint(0.0, 0.0);
finish = NSMakePoint(0.0, 0.0);
dragging = NO;
[self setNeedsDisplay:YES];
}
- (NSView *)hitTest:(NSPoint)point {
NSView *hitView = [super hitTest:point];
return self == hitView ? self:nil;
}
@end
如Handling Mouse Dragging Operations中所述,有两种实现拖动的方法。您的解决方案使应用程序的正常事件循环短路,您必须调用 mouseEntered:
和 mouseExited:
。如果您不想这样做,请实施具有其他缺点的三种方法。