如何在NSTableViewCell中接收mouseDown消息?

时间:2015-08-02 11:57:55

标签: nstableviewcell

我正在尝试创建一个表格视图单元格,显示播放列表中歌曲的评级。我已成功创建了单元格,以便显示当前的星数,并指示当您将鼠标光标悬停在单元格上以获得新的评级时新设置的方式。

问题是虽然mouseEntermouseExitmouseMove就像魅力一样,但我没有得到mouseDown的消息,这是实际更改值的必要条件细胞。

我在互联网上搜索过,但我找不到任何解决方案来解决这个问题。我花了这么多时间试图对此进行排序。我希望任何人都有任何答案或提示我能做些什么。谢谢。

当前实现的完整代码如下:

#import "FavouriteCellView.h"

@implementation FavouriteCellView {
    NSTrackingArea *_trackingArea;
    int _starsRated; //The current rating value
    BOOL _hovering; //YES if the mouse is currently hovering over this cell
    int _starsHovering; //The number of stars hovering, if the mouse is hovering over this cell
}

- (void)awakeFromNib {
    [super awakeFromNib];
    _starsRated = 1;
    _hovering = NO;
    _starsHovering = 0;
    [self createTrackingArea];
}

- (void)createTrackingArea
{
    _trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingMouseEnteredAndExited |NSTrackingActiveInActiveApp | NSTrackingMouseMoved owner:self userInfo:nil];
    [self addTrackingArea:_trackingArea];
}

- (void)updateTrackingAreas{
    [self removeTrackingArea:_trackingArea];
    _trackingArea = nil;
    [self createTrackingArea];
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

//    CGFloat middleX = [self bounds].size.width / 2.0f;
    CGFloat middleY = [self bounds].size.height / 2.0f;

    CGFloat starDivs = [self bounds].size.width / 5.0f;;

    NSColor *starSelectedColor = [NSColor colorWithDeviceRed:0.8f green:0.0f blue:0.4f alpha:1.0f];
    NSColor *starUnselectedColor = [NSColor colorWithDeviceRed:0.5f green:0.5f blue:0.5f alpha:1.0f];
    NSColor *starHoverColor = [NSColor colorWithDeviceRed:1.0f green:0.843f blue:0.0f alpha:1.0f];
    NSColor *starHoverColorSelected = [NSColor colorWithDeviceRed:0.9f green:0.843f blue:0.6f alpha:1.0f];

    for (int i = 0; i < 5; i++) {

        NSColor *useColor = [NSColor redColor];

        if (_hovering && (i <= _starsHovering)) {
            if (i <= _starsRated) {
                useColor = starHoverColorSelected;
            } else {
                useColor = starHoverColor;
            }
        } else if (i <= _starsRated) {
            useColor = starSelectedColor;
        } else {
            useColor = starUnselectedColor;
        }

        [self star:NSMakePoint((starDivs / 2.0f) + starDivs * i, middleY) color:useColor];
    }
}

-(void)star:(NSPoint)center color:(NSColor *)color {
    [color set];

    CGFloat t = (2.0f * M_PI) / 10.0f;

    NSBezierPath *path = [[NSBezierPath alloc] init];

    CGFloat radii1 = 12.0f;
    CGFloat radii2 = 4.0f;

    CGFloat rot = M_PI / 2.0f;

    BOOL first = YES;
    for (int i = 0; i < 10; i++) {
        CGFloat pointX = cos(t * i + rot) * radii1 + center.x;
        CGFloat pointY = sin(t * i + rot) * radii1 + center.y;

        CGFloat tempRadii = radii1;
        radii1 = radii2;
        radii2 = tempRadii;

        if (first) {
            first = NO;
            [path moveToPoint:NSMakePoint(pointX, pointY)];
        }
        else {
            [path lineToPoint:NSMakePoint(pointX, pointY)];
        }
    }

    [path closePath];
    [path fill];

/*
    [[NSColor blackColor] set];
    [path setLineWidth:0.25f];
    [path stroke];
*/
}

-(NSView *)hitTest:(NSPoint)aPoint {
    //THIS GETS CALLED
    return self;
}

-(BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event {
    printf("$");  //DOES NOT GET CALLED
    return YES;
}

-(BOOL)acceptsFirstResponder {
    printf("!");  //DOES NOT GET CALLED
    return YES;
}

-(BOOL)acceptsFirstMouse:(NSEvent *)theEvent {
    printf("8");  //DOES NOT GET CALLED
    return YES;
}

-(void)mouseDown:(NSEvent *)theEvent {
    printf("o");  //DOES NOT GET CALLED
    _starsRated = _starsHovering;
}

-(void)mouseUp:(NSEvent *)theEvent {
    printf("O");  //DOES NOT GET CALLED
}

-(void)mouseEntered:(NSEvent *)theEvent {
    //DOES GET CALLED
    _hovering = YES;
    [self setNeedsDisplay:YES];
}

-(void)mouseExited:(NSEvent *)theEvent {
    //DOES GET CALLED
    _hovering = NO;
    [self setNeedsDisplay:YES];
}

-(void)mouseMoved:(NSEvent *)theEvent {
    //DOES GET CALLED
    NSPoint mouseLocation = [[self window] mouseLocationOutsideOfEventStream];
    mouseLocation = [self convertPoint: mouseLocation
                          fromView: nil];

    int newStarsHoveringValue = mouseLocation.x / ([self bounds].size.width / 5.0f);

    if (newStarsHoveringValue != _starsHovering) {
        _starsHovering = newStarsHoveringValue;
        [self setNeedsDisplay:YES];
    }
}

@end

1 个答案:

答案 0 :(得分:0)

这有点繁琐,但我设法创建了一个有效的解决方案。我将NSTableView子类化,然后使用以下代码覆盖mouseDown

-(void)mouseDown:(NSEvent *)theEvent {
    NSPoint globalLocation = [theEvent locationInWindow];
    NSPoint localLocation = [self convertPoint:globalLocation fromView:nil];
    NSInteger clickedRow = [self rowAtPoint:localLocation];

    if (clickedRow != -1) {
        NSInteger clickedColumn = [self columnAtPoint:localLocation];
        if (clickedColumn != -1) {
            if (clickedColumn == 3) {
                FavouriteCellView *fv = [self viewAtColumn:clickedColumn row:clickedRow makeIfNecessary:NO];
                if (fv != nil) {
                    [fv mouseDown:theEvent];
                }
                return;
            }
        }
    }

    [super mouseDown:theEvent];
}

现在它的工作方式与我想的完全一样。