我应该在NSCell上调用什么方法

时间:2021-06-01 07:06:58

I am writing a custom NSControl with custom NSCells. It is a control, so it has to respond to the mouse. I created an NSTrackingArea over my control, implemented -mouseEntered:, -mouseExited: and -mouseMoved:. (And I will have to implement -mouseUp/Down:, but I have no idea what to do in there, so for now I haven't overridden those methods yet.) In these methods I successfully determine on which cell the mouse currently is. Now I have two questions:

我正在使用自定义NSCells编写自定义NSControl。它是一个控件,所以它必须响应鼠标。我在我的控件上创建了一个NSTrackingArea,实现了-mouseEntered:, - mouseExited:和-mouseMoved:。 (我将不得不实现-mouseUp / Down:,但我不知道该怎么做,所以现在我还没有覆盖那些方法。)在这些方法中,我成功地确定鼠标当前是哪个单元格。现在我有两个问题:

  • Is this a good approach for tracking the mouse? If not, what should I do instead?
  • 这是跟踪鼠标的好方法吗?如果没有,我该怎么办呢?

  • What method should I call on my NSCell on a mouse click, when the mouse enters the cell, when the mouse leaves the cell etc? Apple's docs are not very clear about this.
  • 当鼠标进入细胞,当鼠标离开细胞等时,我应该在鼠标点击时调用NSCell的方法是什么? Apple的文档对此并不十分清楚。

So, basically: When should I call what method on my NSCell to let it respond to mouse events?

所以,基本上:我什么时候应该在我的NSCell上调用哪种方法让它响应鼠标事件?

EDIT:
Rereading the docs, I think I should call NSCell's -trackMouse:inRect:ofView:untilMouseUp: and override -startTrackingAt:inView:, -continueTracking:at:inView: and -stopTracking:at:inView:mouseIsUp:. Again two questions: 1) the docs give the impression these are only called when the mouse is down. Is that correct? Then what should I do instead? 2) Where/when should I call NSCell's -trackMouse:inRect:ofView:untilMouseUp:?

编辑:重读文档,我想我应该调用NSCell的-trackMouse:inRect:ofView:untilMouseUp:和override -startTrackingAt:inView:, - ContinueTracking:at:inView:and -stopTracking:at:inView:mouseIsUp:。还有两个问题:1)文档给人的印象是这些仅在鼠标停止时调用。那是对的吗?那我该怎么做呢? 2)我应该在何时/何时调用NSCell的-trackMouse:inRect:ofView:untilMouseUp:?

1 个解决方案

#1


1  

I ended up implementing my own mouse tracking mechanism:

我最终实现了自己的鼠标跟踪机制:

// MyControl.m:

- (void)mouseDown:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        currentCell = cell;
        [currentCell mouseDown:theEvent];
    }
}

- (void)mouseUp:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        [cell mouseUp:theEvent];
    }
}

- (void)mouseEntered:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        currentCell = cell;
        [currentCell mouseEntered:theEvent];
    }
}

- (void)mouseExited:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        [cell mouseExited:theEvent];
        currentCell = nil;
    }
}

- (void)mouseMoved:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    MKListCell *cell;
    if (currentCellIndex < [cells count]) {
        cell = [cells objectAtIndex:currentCellIndex];
    }
    if (currentCell != cell) {
        [currentCell mouseExited:theEvent];
        [cell mouseEntered:theEvent];
        currentCell = cell;
    }
    else {
        [currentCell mouseMoved:theEvent];
    }
}

- (void)mouseDragged:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    MKListCell *cell = nil;
    if (currentCellIndex < [cells count]) {
        cell = [cells objectAtIndex:currentCellIndex];
    }
    if (currentCell != cell) {
        [currentCell mouseExited:theEvent];
        [cell mouseEntered:theEvent];
        currentCell = cell;
    }
    else {
        [currentCell mouseMoved:theEvent];
    }   
}

- (int)indexOfCellAtPoint:(NSPoint)p {
    int cellIndex = (self.bounds.size.height - p.y) / cellHeight;
    return cellIndex;
}

And of course, in MyCell.h:

当然,在MyCell.h中:

- (void)mouseDown:(NSEvent *)event;
- (void)mouseUp:(NSEvent *)event;
- (void)mouseMoved:(NSEvent *)event;
- (void)mouseEntered:(NSEvent *)event;
- (void)mouseExited:(NSEvent *)event;

With an empty implementation for those methods (so the compiler doesn't complain and I can leave the implementation of the mouse handling methods to subclasses).

使用这些方法的空实现(因此编译器不会抱怨,我可以将鼠标处理方法的实现留给子类)。

#1


1  

I ended up implementing my own mouse tracking mechanism:

我最终实现了自己的鼠标跟踪机制:

// MyControl.m:

- (void)mouseDown:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        currentCell = cell;
        [currentCell mouseDown:theEvent];
    }
}

- (void)mouseUp:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        [cell mouseUp:theEvent];
    }
}

- (void)mouseEntered:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        currentCell = cell;
        [currentCell mouseEntered:theEvent];
    }
}

- (void)mouseExited:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    if (currentCellIndex < [cells count]) {
        MKListCell *cell = [cells objectAtIndex:currentCellIndex];
        [cell mouseExited:theEvent];
        currentCell = nil;
    }
}

- (void)mouseMoved:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    MKListCell *cell;
    if (currentCellIndex < [cells count]) {
        cell = [cells objectAtIndex:currentCellIndex];
    }
    if (currentCell != cell) {
        [currentCell mouseExited:theEvent];
        [cell mouseEntered:theEvent];
        currentCell = cell;
    }
    else {
        [currentCell mouseMoved:theEvent];
    }
}

- (void)mouseDragged:(NSEvent *)theEvent {
    int currentCellIndex = [self indexOfCellAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
    MKListCell *cell = nil;
    if (currentCellIndex < [cells count]) {
        cell = [cells objectAtIndex:currentCellIndex];
    }
    if (currentCell != cell) {
        [currentCell mouseExited:theEvent];
        [cell mouseEntered:theEvent];
        currentCell = cell;
    }
    else {
        [currentCell mouseMoved:theEvent];
    }   
}

- (int)indexOfCellAtPoint:(NSPoint)p {
    int cellIndex = (self.bounds.size.height - p.y) / cellHeight;
    return cellIndex;
}

And of course, in MyCell.h:

当然,在MyCell.h中:

- (void)mouseDown:(NSEvent *)event;
- (void)mouseUp:(NSEvent *)event;
- (void)mouseMoved:(NSEvent *)event;
- (void)mouseEntered:(NSEvent *)event;
- (void)mouseExited:(NSEvent *)event;

With an empty implementation for those methods (so the compiler doesn't complain and I can leave the implementation of the mouse handling methods to subclasses).

使用这些方法的空实现(因此编译器不会抱怨,我可以将鼠标处理方法的实现留给子类)。