【问题标题】:Draw into a NSView via mouse event通过鼠标事件绘制到 NSView
【发布时间】:2013-02-21 21:55:31
【问题描述】:

我是编程、objective-c(和 stackoverflow)的新手。我正在学习并非常缓慢地前进;)但后来我遇到了一个问题,谷歌无法解决。我有一个窗口和一个 NSview,然后添加了一个鼠标事件,应该将坐标绘制到我的视图中,但它没有。有趣的是:它是在鼠标移到我的应用程序窗口的窗口按钮上时绘制的...

- (void)drawRect:(NSRect)dirtyRect {
   NSPoint imagePos = NSMakePoint(0, 0);
   NSImage *aImage = [NSImage imageNamed:@"mw_bg01.png"];
   [aImage dissolveToPoint:imagePos fraction:1.0];
}
- (void)mouseDown:(NSEvent*)theEvent;{
   mouseLoc = [NSEvent mouseLocation];
   mousePosX = mouseLoc.x;mousePosY = mouseLoc.y;
   NSString* mouseString = [NSString stringWithFormat:@"%d", mousePosX];
   NSPoint textPoint = NSMakePoint(5, 5);
   NSMutableDictionary *textAttrib = [[NSMutableDictionary alloc] init];
   [textAttrib setObject:[NSFont fontWithName:@"Helvetica Light" size:10]
               forKey:NSFontAttributeName];
   [textAttrib setObject:[NSColor grayColor] forKey:NSForegroundColorAttributeName];
   [mouseString drawAtPoint:textPoint withAttributes:textAttrib];
}

我不知道该怎么做,有什么建议吗?谢谢!

【问题讨论】:

  • 这段代码在哪里?看起来您已经编写了 mouseDown 处理程序。根据此代码的位置(例如,在应用程序与视图中或其他任何地方),它可能只是恰好是按钮的委托而不是视图的委托。
  • 它在视图中。我使用了一个 mouseDown 处理程序,因为我想在我的视图中测试绘图并且 mousemove 没有被调用。
  • 而且:我根本没有按钮,我的意思是 3 个 osx 窗口按钮...

标签: objective-c macos mouseevent nsview


【解决方案1】:

您不应该在-mouseDown: 方法中进行绘图。相反,您必须在-drawRect:(或从-drawRect: 调用的方法)中完成所有绘图。试试这样的:

@interface MyView ()
    @property NSPoint lastMousePoint;
@end

@implementation MyView

- (void)drawLastMousePoint
{
    NSString *mouseString = NSStringFromPoint(self.lastMousePoint);
    NSPoint textPoint = NSMakePoint(5, 5);
    NSMutableDictionary *textAttrib = [[NSMutableDictionary alloc] init];
    [textAttrib setObject:[NSFont fontWithName:@"Helvetica Light" size:10]
                forKey:NSFontAttributeName];
    [textAttrib setObject:[NSColor grayColor] forKey:NSForegroundColorAttributeName];
    [mouseString drawAtPoint:textPoint withAttributes:textAttrib];
}

- (void)drawRect:(NSRect)dirtyRect 
{
    NSPoint imagePos = NSMakePoint(0, 0);
    NSImage *aImage = [NSImage imageNamed:@"mw_bg01.png"];
    [aImage dissolveToPoint:imagePos fraction:1.0];

    [self drawLastMousePoint];
}

- (void)mouseDown:(NSEvent*)theEvent;
{
    self.lastMousePoint = [theEvent locationInWindow];
    [self setNeedsDisplay:YES];
}

@end

当您收到鼠标按下事件时,您只需存储鼠标按下的位置。绘图是在 -drawLastMousePoint 中完成的,您可以在 -drawRect: 方法中调用它。由于您知道在任何时候单击鼠标都需要重绘,因此您调用-setNeedsDisplay: 通知视图它需要重绘。请注意,重绘不会立即发生,而是会在下一次通过运行循环时发生。换句话说,您是在说“嘿,发生了一些变化,我需要重新绘制视图的内容。请尽快再次致电-drawRect:!”

另一个注意事项:+[NSEvent mouseLocation] 真正设计用于获取当前鼠标位置在事件流之外。通常,在-mouseDown: 方法中,您在作为参数传递给该方法的NSEvent 上调用-locationInWindow。如果需要转换为本地/视图坐标,请致电[self convertPoint:[theEvent locationInWindow] fromView:nil];

【讨论】:

  • 谢谢。我需要学习很多 ;) 但有一件事:当我调用 setNeedsDisplay 时,它也会绘制 mw_bg01.png,对吗?这很慢,不是吗?
  • 我们在某一时刻都是全新的 :)。是的,它会再次绘制 PNG。您不必提前担心这会很慢,而是应该测试一下它是否足够慢以至于它确实有所作为,然后才花时间改变它的工作方式。通常,将静态 PNG 绘制到屏幕上非常快。如果您确实需要提高性能,有几个选项,包括:仅重绘视图的一部分(请参阅-setNeedsDisplayInRect:),处理在当前视图的子视图的不同视图中绘制鼠标点,使用 CALayers等。
  • @fw2601 这实际上不适合您吗?你为什么不接受这个答案?
  • 它工作得很好,我现在试试这个 setNeedsDisplayInRect 东西。我不知道这种不可接受的事情是怎么发生的...试图投票给你,但不能
  • @fw2601,好的,很好。我只是想确保您在实施它时没有遇到问题!在您获得至少 15 个声望点之前,您将无法对答案进行投票。
猜你喜欢
  • 2011-09-29
  • 1970-01-01
  • 2013-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
相关资源
最近更新 更多