I’m ba-ack! I really have been neglecting this block, and I’m going to try to post more often.

The subject of this post is the NSScroller class, since I recently needed to work with it and I found the documentation lacking and a bit out of date. Further, I couldn’t find much about the class on the web, and most of the comments involved sub-classing the control, which really isn’t a good idea. So here is what I’ve learned about NSScroller.

You almost never need to use NSScroller in your code, because NSScrollView will do everything you need. Also, consider using NSSlider instead.

So, you’ve thought about your UI design, and decided that a scroller really is the way to go. So, fire up Interface Builder, open your window, and drag a scroller instance from the palette to your window.

What’s that?

You can’t find the scroller objects in IB? That’s because they’re not there; you’ll have to create the scroller in code. It’s really not that hard. First, figure out where you want the scroller to live on the screen. You’ll need the x,y co-ordinates of the bottom left corner. Now, make a rect with those co-ordinates and the width and length of the scroller you want.

For my horizontal scroller, it looks like this

    NSRect winRect = [window frame];
    NSRect scrollFrame = NSMakeRect(20.0, 20.0, 
        winRect.size.width -40.0,[NSScroller scrollerWidth] );
    hScroller = [[NSScroller alloc] initWithFrame:scrollFrame];

Here, hScroller is a property so that you can get at it from other places in your code.

Now, there are a few setup steps that are necessary for the scroller to appear in the window.

    // Proportion is the amount of the scroller that
    // the knob takes up,
    // the width of the knob for a horizontal scroller,
    //  or the height for a vertical scroller.
    [hScroller setKnobProportion:0.05];
    // the scroller double value is the position of
    // the knob on the slider, with a range of
    // 0.0 to 1.0
    [hScroller setDoubleValue:0.5];
    [hScroller setEnabled:YES];
    [[window contentView] addSubview:hScroller];

The setEnabled message is necessary because the control defaults to disabled. I suspect this is for the scrollview implementation.

Now, if you run your program, you’ll see a scroller that you can interact with. The arrows work, and sliding the knob works. The next step is dealing with the interactions in code. You need to connect the scroller action to the controller.

So, back in the awakeFromNib method, add two more lines.

SEL mySelector = NSSelectorFromString(@"scrollAction:");
	[hScroller setAction:mySelector];

And that’s it; setup complete.

Now, to handle the messages sent by the scroller, you need to implement the scrollAction method. The trick seems to be to read the hitPart property to figure out which part on the scroller was clicked. Here is a sample handler:

- (IBAction)scrollAction:(id)sender
  switch ([hScroller hitPart]) {
  case NSScrollerNoPart:
  case NSScrollerDecrementPage:
  case NSScrollerKnob:
    NSLog(@"scrollerKnob, value= %f",[hScroller doubleValue]);
  case NSScrollerIncrementPage:
  case NSScrollerDecrementLine:
  case NSScrollerIncrementLine:
  case NSScrollerKnobSlot:
    NSLog(@"knobSlot, value= %f",[hScroller doubleValue]);

Now, when you get a page or line change you’ll need to adjust the doubleValue accordingly, to reposition the knob.

By experimenting with these messages you should be able to adapt the scroller to suit your needs.

One last thing: the top of the Apple documentation states that setFloatValue:knobProportion: is a commonly used method, but further on down you’ll learn that it is, in fact, deprecated. You should be using setDoubleValue: and setKnobProportion instead.

That’s it. If you have any questions, or anything to add, please let me know in the comments.

3 thoughts on “NSScroller

  1. There’s no good reason to use NSSelectorFromString here. Use @selector(scrollAction:) instead; it’s simpler and more efficient.

  2. This post saves my life, regardless of @selector or NSSelectorFromString, thanks a lot (yes, I know it is an old post…., but anyway)

  3. Thank you man, that setEnabled:YES call is what makes all the difference. wow. Now if i can get the position to change.

Leave a Reply

Your email address will not be published. Required fields are marked *