0

我正在尝试制作一个表格视图单元格,显示播放列表中歌曲的评分。我已成功创建单元格,以便它显示当前的星数,并指示当您将鼠标光标悬停在单元格上以给出新评级时新设置将如何。

问题是,虽然mouseEnter,mouseExitmouseMove像魅力一样工作,但我没有收到任何消息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
4

1 回答 1

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];
}

现在它就像我想要的那样工作。

于 2015-08-02T18:44:03.777 回答