【问题标题】:Core plot mouseMoved核心情节 mouseMoved
【发布时间】:2023-05-15 17:08:01
【问题描述】:

当鼠标移动/悬停在符号或线条上时,我想在 scatterplot 中显示(注释)值。我知道之前有人问过这个问题,但我只能找到需要用户单击图表才能显示此信息的答案。我试图在我的 plotView 委托中实现 mouseMoved 方法:

- (void)mouseMoved:(NSEvent *)theEvent
{
    NSPoint location = [hostingView convertPoint: [theEvent locationInWindow] fromView: nil];
    CGPoint mouseLocation = NSPointToCGPoint(location);
    CGPoint pointInHostedGraph = [hostingView.layer convertPoint: mouseLocation toLayer:  plotItem.graph.plotAreaFrame.plotArea];

    NSUInteger index = [self.plotItem.dataSourceLinePlot indexOfVisiblePointClosestToPlotAreaPoint: pointInHostedGraph];
    NSLog(@"test: %lu",(unsigned long)index);

}

这里,plotItem 是 NSObject 的子类,定义类似于 example 中的 PlotItem.h,托管视图是 CPTGraphHostingView 的一个实例。我还要补充:

    CPTGraphHostingView *hostedlayer=[self.plotItem updateView:hostingView height:hostingView.frame.size.height width:hostingView.frame.size.width];

    [self.plotItem renderInView:hostedlayer withTheme:theme animated:YES withData:self.myFlattenedNodes];

    hostedlayer.window.acceptsMouseMovedEvents = YES;
    [hostedlayer.window makeFirstResponder:hostingView];

但是我的 mouseMoved 方法没有被调用。我在这里做错了什么,因为我无法让 mouseMoved 响应我的悬停。我是否需要将 NSTrackingArea 添加到 hostsLayer ?建议表示赞赏。 T

更新和解决方案: 我遵循了 Erics 的建议并将我的 CPTGraphHostingView 子类化,并在其中实现了以下内容:

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.window.acceptsMouseMovedEvents = YES;
        [self.window makeFirstResponder:self];

        area = [[NSTrackingArea alloc] initWithRect:self.frame
                                            options: (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow| NSTrackingActiveAlways)
                                              owner:self userInfo:nil];

        [self addTrackingArea:area];
        [self becomeFirstResponder];
    }
    return self;
}

- (void)updateTrackingAreas {
    [self removeTrackingArea:area];
    area = [[NSTrackingArea alloc] initWithRect:self.frame
                                    options: (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow| NSTrackingActiveAlways)
                                      owner:self userInfo:nil];
    [self addTrackingArea:area];
}

- (void)mouseMoved:(NSEvent *)theEvent
{
    NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
    CGPoint mouseLocation = NSPointToCGPoint(location);
    [self setLocationOfMouse:[self.layer convertPoint: mouseLocation toLayer:nil]];
}

-(void) dealloc{
    [self removeTrackingArea:area];
}

我还定义了类的属性:

CGPoint locationOfMouse;
NSTrackingArea *area;

在我的控制器中,我为 locationOfMouse 属性添加了一个观察者:

    [self.plotItem.graphHostingView addObserver:self
                        forKeyPath:@"locationOfMouse"
                           options:0
                           context:NULL];

这触发了我绘制注释的方法:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
     if ( [keyPath isEqualToString:@"locationOfMouse"] ) {
        CGPoint location = self.plotItem.graphHostingView.locationOfMouse;
        [self.plotItem mouseMovedOverGraph:location];    
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object
                           change:change context:context];
    }
} 

【问题讨论】:

  • 您是否将委托设置为自我?
  • 是的,代理设置为自己。

标签: objective-c macos cocoa core-plot


【解决方案1】:

Core Plot 不会将鼠标移动事件传递给它的任何代理。子类CPTGraphHostingView(它是NSView的子类)并在那里实现-mouseMoved:方法。 Core Plot 仅使用鼠标向下、拖动和向上事件,因此您不会干扰任何内置事件处理。

【讨论】:

  • @ErikSkroch 感谢您的建议!它工作得很好。但是,您的评论让我想知道我是否正在做一些我不应该做的可能会导致问题的事情? Core Plot 不想包含 mouseMoved 有什么特别的原因吗?再次感谢! T.
  • Core Plot 使用-mouseDragged: 进行绘图滚动。我们不需要-mouseMoved: 做任何事情。