Пользовательская ручка NSSliderCell не следует за мышью при отслеживании - PullRequest
2 голосов
/ 26 августа 2011

Я реализовал пользовательский NSSliderCell, который использует ручку совсем другого размера, чем по умолчанию (это для интерактивной выставки - я не могу использовать какие-либо элементы управления Mac OS X по умолчанию).

Хотя ползунок отображается и работает правильно (ручка перемещается от конца к концу и т. Д.), Если вы внимательно посмотрите, вы увидите странное поведение: перемещение мыши, скажем, на 20 пикселей, приведет к перемещению ручки на 30 пикселей , Это означает, что ручка может достигнуть конца ползунка (и ползунок будет иметь максимальное значение), прежде чем мышь достигнет конца.

Это выглядит очень странно и противоречит всем ожиданиям. Интересно, что мне нужно изменить, чтобы ручка следовала за мышью и не двигалась быстрее.

Ответы [ 2 ]

3 голосов
/ 26 августа 2011

ОК, как всегда, решение было самым простым.

Вот самый простой код, который вам нужен, чтобы иметь очень настраиваемый слайдер:

#import "CSSSliderCell.h"
#define KNOB_WIDTH 20
#define KNOB_HEIGHT 126
#define SLIDER_WIDTH 13

@implementation CSSSliderCell

- (void)drawKnob:(NSRect)rect
{
    // knobImage is an NSImage 
    [knobImage drawInRect:rect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];

}

- (void)drawBarInside:(NSRect)cellFrame flipped:(BOOL)flipped
{   
    NSRect slideRect = cellFrame;
    NSColor *backColor = [NSColor redColor];
    if ([(NSSlider*) [self controlView] isVertical] == YES)
    {
        slideRect.size.width = SLIDER_WIDTH;
        slideRect.origin.x += (cellFrame.size.width - SLIDER_WIDTH) * 0.5;
    } else {
        slideRect.size.height = SLIDER_WIDTH;
        slideRect.origin.y += (cellFrame.size.height - SLIDER_WIDTH) * 0.5;
    }

    NSBezierPath *bezierPath = [NSBezierPath bezierPathWithRoundedRect:slideRect xRadius:SLIDER_WIDTH * 0.5 yRadius:SLIDER_WIDTH * 0.5];  
    [backColor setFill];
    [bezierPath fill];

}


- (NSRect)knobRectFlipped:(BOOL)flipped{

    CGFloat value = ([self doubleValue]  - [self minValue])/ ([self maxValue] - [self minValue]);
    NSRect defaultRect = [super knobRectFlipped:flipped];
    NSRect myRect = NSMakeRect(0, 0, 0, 0);
    if ([(NSSlider*) [self controlView] isVertical] == YES)
    {
        myRect.size.width = KNOB_WIDTH;
        myRect.size.height = KNOB_HEIGHT;
        if (!flipped) {
            myRect.origin.y = value * ([[self controlView] frame].size.height - KNOB_HEIGHT);
        } else {
            myRect.origin.y = (1.0 - value) * ([[self controlView] frame].size.height - KNOB_HEIGHT);
        }
        myRect.origin.x = defaultRect.origin.x;

    } else {
        myRect.size.width = KNOB_HEIGHT;
        myRect.size.height = KNOB_WIDTH;
        myRect.origin.x = value * ([[self controlView] frame].size.width - KNOB_HEIGHT);
        myRect.origin.y = defaultRect.origin.y;

    }
    return myRect;
}
- (BOOL)_usesCustomTrackImage
{
    return YES;
}


@end

Это может иметь проблемы, нопока что как в горизонтальной, так и в вертикальной ориентации это работает хорошо.

1 голос
/ 23 декабря 2011

orestis, твой код мне очень помогает. Спасибо!

Однако положение ручки (myRect.origin) неверно. Я изменил код (а также удалил жестко закодированные макросы).

- (NSRect)knobRectFlipped:(BOOL)flipped {
    float KNOB_WIDTH = [knobImage size].width;
    float KNOB_HEIGHT = [knobImage size].height;
    CGFloat value = ([self doubleValue]  - [self minValue])/ ([self maxValue] - [self minValue]);
    NSRect defaultRect = [super knobRectFlipped:flipped];
    NSRect myRect = NSMakeRect(0, 0, 0, 0);
    if ([(NSSlider*) [self controlView] isVertical] == YES)
    {
        //...   
    } else {
        myRect.size.width = KNOB_WIDTH;
        myRect.size.height = KNOB_HEIGHT;
        myRect.origin.x = value * ([[self controlView] frame].size.width - KNOB_WIDTH);
        myRect.origin.y = defaultRect.origin.y + defaultRect.size.height/2.0 - myRect.size.height/2.0; // Fixed the position

    }
    return myRect;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...