我正在用自定义nscell编写一个自定义NSControl。它是一个控件,所以它必须响应鼠标。我在我的控制下创建了一个NSTrackingArea,实现了-mouseEntered:
, -mouseExited:
和-mouseMoved:
。(我将不得不实现-mouseUp/Down:
,但我不知道在那里做什么,所以现在我还没有覆盖这些方法。)在这些方法中,我成功地确定了鼠标当前在哪个细胞上。现在我有两个问题:
- 这是跟踪鼠标的好方法吗?如果不是,我该怎么做呢?
- 当鼠标进入单元格时,当鼠标离开单元格时,我应该在我的ncell上调用什么方法?苹果的文档对此不是很清楚。
所以,基本上:我什么时候应该在我的NSCell上调用什么方法来让它响应鼠标事件?
编辑:
重读文档,我想我应该调用NSCell的-trackMouse:inRect:ofView:untilMouseUp:
和覆盖-startTrackingAt:inView:
, -continueTracking:at:inView:
和-stopTracking:at:inView:mouseIsUp:
。还有两个问题:1)文档给人的印象是,只有当鼠标按下时才会调用这些文档。对吗?那我该怎么办呢?2)我应该在哪里/何时调用NSCell的-trackMouse:inRect:ofView:untilMouseUp:
我最终实现了自己的鼠标跟踪机制:
// 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;
}
当然,在MyCell.h
中:
- (void)mouseDown:(NSEvent *)event;
- (void)mouseUp:(NSEvent *)event;
- (void)mouseMoved:(NSEvent *)event;
- (void)mouseEntered:(NSEvent *)event;
- (void)mouseExited:(NSEvent *)event;
这些方法的实现为空(因此编译器不会抱怨,我可以将鼠标处理方法的实现留给子类)。