custom view won't update

  • hello.

    I have a window with a custom view and 3 sliders. the view is
    assigned to a custom class which is a subclass of NSView. when I
    change the size of the window, drawRect: is called, the view displays
    its stuff, no problem there. but: I want the view to update when any
    one of the sliders is moved. how do I do that? I've tried [self
    setNeedsDisplay], but that didn't work. I tried [self display], but
    that didn't work either. so I tried both, but the view still refuses
    to update when i move a slider. What am I doing wrong?

    --
    GPG Key ID: 92AD877F7E4E32B9
    Fingerprint: 16B0 7DCD 3AB0 0C45 F5FD  581D 92AD 877F 7E4E 32B9
  • On Sep 8, 2007, at 4:50 PM, H M wrote:

    > hello.
    >
    > I have a window with a custom view and 3 sliders. the view is
    > assigned to a custom class which is a subclass of NSView. when I
    > change the size of the window, drawRect: is called, the view
    > displays its stuff, no problem there. but: I want the view to
    > update when any one of the sliders is moved. how do I do that? I've
    > tried [self setNeedsDisplay], but that didn't work. I tried [self
    > display], but that didn't work either. so I tried both, but the
    > view still refuses to update when i move a slider. What am I doing
    > wrong?

    Who is getting the action event from the slider? Is it actually
    getting it? You check using the debugger?

    -Shawn
  • On 9. Sep 2007, at 3:05, Shawn Erickson wrote:

    >
    > On Sep 8, 2007, at 4:50 PM, H M wrote:
    >
    >> hello.
    >>
    >> I have a window with a custom view and 3 sliders. the view is
    >> assigned to a custom class which is a subclass of NSView. when I
    >> change the size of the window, drawRect: is called, the view
    >> displays its stuff, no problem there. but: I want the view to
    >> update when any one of the sliders is moved. how do I do that?
    >> I've tried [self setNeedsDisplay], but that didn't work. I tried
    >> [self display], but that didn't work either. so I tried both, but
    >> the view still refuses to update when i move a slider. What am I
    >> doing wrong?
    >
    > Who is getting the action event from the slider? Is it actually
    > getting it? You check using the debugger?

    My custom class has 3 action methods, one for each slider. yes, they
    get called, and the variables are set. after that, [self
    setNeedsDisplay:YES] and [self display] are executed, but they don't
    have any effect.

    --
    GPG Key ID: 92AD877F7E4E32B9
    Fingerprint: 16B0 7DCD 3AB0 0C45 F5FD  581D 92AD 877F 7E4E 32B9
  • > My custom class has 3 action methods, one for each slider. yes, they
    > get called, and the variables are set. after that, [self
    > setNeedsDisplay:YES] and [self display] are executed, but they don't
    > have any effect.

      There is not enough information to give you much help. Post your code.

    --
    I.S.
  • On 10. Sep 2007, at 19:09, I. Savant wrote:

    >> My custom class has 3 action methods, one for each slider. yes, they
    >> get called, and the variables are set. after that, [self
    >> setNeedsDisplay:YES] and [self display] are executed, but they don't
    >> have any effect.
    >
    > There is not enough information to give you much help. Post your
    > code.

    ok, here is one of the action methods. the other 2 are exactly the
    same, except they are assigned to the other 2 sliders, and the name
    of the variable is different. all 3 variables are declared as double
    in the top of the implementation file.

    - (IBAction)setDec:(id)sender {
    viewDec = (double) [sender floatValue];  // this line works perfectly
    [self setNeedsDisplay:YES]; //this one is executed but has no
    visible effect at all.
    [self display];  //same here
    }

    the header file declares the outlets in the following format:

    IBOutlet NSSlider *DecSlider;

    erm, do I NEED those outlets? or is it enough to call [sender
    floatValue]? gotta try that...

    --
    GPG Key ID: 92AD877F7E4E32B9
    Fingerprint: 16B0 7DCD 3AB0 0C45 F5FD  581D 92AD 877F 7E4E 32B9
  • > ok, here is one of the action methods. the other 2 are exactly the
    > same, except they are assigned to the other 2 sliders, and the name
    > of the variable is different. all 3 variables are declared as double
    > in the top of the implementation file.
    >
    > - (IBAction)setDec:(id)sender {
    > viewDec = (double) [sender floatValue];  // this line works perfectly
    > [self setNeedsDisplay:YES]; //this one is executed but has no
    > visible effect at all.
    > [self display];  //same here
    > }

      You need to read the documentation for those two methods.
    -setNeedsDisplay: flags the view as needing display but does not
    immediately do so (for optimization purposes). -display forces the
    view to redraw itself immediately.

    If you want changes to happen while moving the slider, you need to
    check the slider's "Continuously send action while sliding" checkbox
    in Interface Builder.

    Regarding necessary code, what's in your view's -drawRect: method?
    "Post your code" means you need to post all the relevant code. The
    contents of your custom -drawRect: method is certainly that.

    > the header file declares the outlets in the following format:
    >
    > IBOutlet NSSlider *DecSlider;
    >
    >
    > erm, do I NEED those outlets? or is it enough to call [sender
    > floatValue]? gotta try that...

      You don't need them unless you want to message them. The "sender"
    argument refers to the sender of the message (in this case, your
    slider), so it will be fine in this case.

    --
    I.S.
  • On 10. Sep 2007, at 19:40, I. Savant wrote:

    > -display forces the view to redraw itself immediately.

    meaning it should call the drawRect method, right? but that method
    does not get called when i move a slider. it  is only called when i
    change the size of the window and thereby the size of the view.

    > If you want changes to happen while moving the slider, you need to
    > check the slider's "Continuously send action while sliding" checkbox
    > in Interface Builder.

    I know. I've done that.

    > Regarding necessary code, what's in your view's -drawRect: method?
    > "Post your code" means you need to post all the relevant code. The
    > contents of your custom -drawRect: method is certainly that.

    I fail to see what difference the code in the drawRect method can
    make if it isn't even called...

    <outlets>

    > You don't need them unless you want to message them. The "sender"
    > argument refers to the sender of the message (in this case, your
    > slider), so it will be fine in this case.

    I turned those lines into comments and re-built the program, and it
    behaved exactly the same way. so I guess I won't need them for this
    version.

    I guess I better keep them, because i plan to add some new features
    like double-click on the view, in which case I want the sliders to be
    in the correct positions for the new values...

    --
    GPG Key ID: 92AD877F7E4E32B9
    Fingerprint: 16B0 7DCD 3AB0 0C45 F5FD  581D 92AD 877F 7E4E 32B9
  • On 9/10/07, H M <hmiersch...> wrote:
    >> -display forces the view to redraw itself immediately.
    >
    > meaning it should call the drawRect method, right? but that method
    > does not get called when i move a slider. it  is only called when i
    > change the size of the window and thereby the size of the view.

      It depends. Sorry, but there's simply not enough detail to give you
    much more than that.

    >> Regarding necessary code, what's in your view's -drawRect: method?
    >> "Post your code" means you need to post all the relevant code. The
    >> contents of your custom -drawRect: method is certainly that.
    >
    > I fail to see what difference the code in the drawRect method can
    > make if it isn't even called...

      Actually, you said:

    > when I change the size of the window, drawRect: is called

      Then you said:

    > I've tried [self
    > setNeedsDisplay], but that didn't work. I tried [self display], but
    > that didn't work either. so I tried both, but the view still refuses
    > to update when i move a slider.

      Now that I know you meant -drawRect: *is not* called when your
    action methods are called, I know that the problem is probably not
    within -drawRect: ... you need to be *specific*. Also, that you 'fail
    to see' the relevance of something is itself irrelevant. If you knew
    what you were missing, you wouldn't be missing it, right? Right.

      So ... assuming:

      1: Your action methods are in the same NSView subclass as your
    -drawRect: method
      2: Everything is wired up properly in Interface Builder (outlets /
    actions are connected ... and double-checked)
      3: Your action methods are in fact being called (not just -drawRect:)
      4: You're receiving no errors in your run log

      Then:

      1: "self" should definitely refer to the view, so calling -display
    should definitely trigger a re-draw
      2: The action methods should be changing the appropriate values and
    triggering a redraw which will use those new values
      3: Even if things are not updated immediately as you drag, they
    should at least be updated when you've finished dragging the slider,
    so everything should work wonderfully.

      So it appears you're missing something fundamental in your setup.
    Without more information (POST. YOUR. CODE.) it's hard to tell you
    what's wrong. I realize it can be difficult in a large or proprietary
    project (ISOLATE THE PROBLEM AND SHARE THE ISOLATED TEST PROJECT) but
    hey, you're asking the public for help so the legwork and make it easy
    for us.

    --
    I.S.
  • On Sep 10, 2007, at 11:32 AM, H M wrote:

    >
    > On 10. Sep 2007, at 19:09, I. Savant wrote:
    >
    >>> My custom class has 3 action methods, one for each slider. yes, they
    >>> get called, and the variables are set. after that, [self
    >>> setNeedsDisplay:YES] and [self display] are executed, but they don't
    >>> have any effect.
    >>
    >> There is not enough information to give you much help. Post your
    >> code.
    >
    > ok, here is one of the action methods. the other 2 are exactly the
    > same, except they are assigned to the other 2 sliders, and the name
    > of the variable is different. all 3 variables are declared as
    > double in the top of the implementation file.
    >
    > - (IBAction)setDec:(id)sender {
    > viewDec = (double) [sender floatValue];  // this line works
    > perfectly
    > [self setNeedsDisplay:YES]; //this one is executed but has no
    > visible effect at all.
    > [self display];  //same here
    > }

    It seems a little strange that an NSView subclass has IBActions/
    IBOutlets... yet the above code seems to imply that.

    Can you please outline which classes contain which methods and which
    is the NSView subclass? Also can you describe how they are
    connected / instantiated in the nib?

    Given what you have posted so far I believe you are not sending the
    setNeedsDisplay: message to an instance of your view that is actually
    in the view hierarchy of your window but one that is either
    instantiated off by itself in the nib or instantiated in code (and
    not the one in the view hierarchy).

    Using the debugger to note the address of the instances involved
    would help detect this type of issue as would using logging (for
    example NSLog(@"%s - %p", __FUNCTION__, self);)

    -Shawn
  • > It seems a little strange that an NSView subclass has IBActions/
    > IBOutlets... yet the above code seems to imply that.

    hm, come to think of it, i'd say you're right, they should be in a
    controller class. that means i have to access the variables using
    accessor methods, but that shouldn't be a problem. the question is,
    how do I get that controller class to update my view?

    > Can you please outline which classes contain which methods and
    > which is the NSView subclass? Also can you describe how they are
    > connected / instantiated in the nib?

    the NSView subclass is called Sky, and it contains the 3 action
    methods, the 3 outlets, drawRect: and all the necessary variables,
    mostly double.
    in InterfaceBuilder I subclassed NSView, renamed the new class, added
    the outlets and the actions, then I instantiated it and connected the
    sliders to their methods and outlets. after that, i created the files
    and went back to xcode.

    > Given what you have posted so far I believe you are not sending the
    > setNeedsDisplay: message to an instance of your view that is
    > actually in the view hierarchy of your window but one that is
    > either instantiated off by itself in the nib or instantiated in
    > code (and not the one in the view hierarchy).

    that would explain why it doesn't work. I'm gonna try to find out...
  • >> Given what you have posted so far I believe you are not sending
    >> the setNeedsDisplay: message to an instance of your view that is
    >> actually in the view hierarchy of your window but one that is
    >> either instantiated off by itself in the nib or instantiated in
    >> code (and not the one in the view hierarchy).
    >
    > that would explain why it doesn't work. I'm gonna try to find out...

    I put an NSLog into drawRect: and one in one of the action methods,
    and they reported different addresses (or whatever that number means).
    Ok, so now I know why it doesn't work, now the question is, what can
    I do about it?

    --
    GPG Key ID: 92AD877F7E4E32B9
    Fingerprint: 16B0 7DCD 3AB0 0C45 F5FD  581D 92AD 877F 7E4E 32B9
  • On Sep 11, 2007, at 8:16 AM, H M wrote:

    >> It seems a little strange that an NSView subclass has IBActions/
    >> IBOutlets... yet the above code seems to imply that.
    >
    > hm, come to think of it, i'd say you're right, they should be in a
    > controller class. that means i have to access the variables using
    > accessor methods, but that shouldn't be a problem. the question is,
    > how do I get that controller class to update my view?

    Please excuse me barging in to ask a quick question of someone: I
    have a subclass of NSView also. It has an IBOutlet for its
    controller. Is this the correct way to get data from the controller
    to the view?
  • On 11 Sep 2007, at 13:24, Paul Bruneau wrote:

    > On Sep 11, 2007, at 8:16 AM, H M wrote:
    >
    >>> It seems a little strange that an NSView subclass has IBActions/
    >>> IBOutlets... yet the above code seems to imply that.
    >>
    >> hm, come to think of it, i'd say you're right, they should be in a
    >> controller class. that means i have to access the variables using
    >> accessor methods, but that shouldn't be a problem. the question
    >> is, how do I get that controller class to update my view?
    >
    > Please excuse me barging in to ask a quick question of someone: I
    > have a subclass of NSView also. It has an IBOutlet for its
    > controller. Is this the correct way to get data from the controller
    > to the view?

    It's usually better to post a question in a new thread, rather than
    invading an existing thread with another question.

    However, the answer to your question is that it's *one* way to do it,
    yes.  A lot of the existing Cocoa views have a "dataSource" outlet
    for this very purpose.

    It isn't the only way, however.  Some views hold data themselves
    (though this is rare, and you run the risk that your view will be
    abused as a data store, which breaks MVC quite badly).  Also, some
    views support Cocoa bindings as a way to get data into them, and you
    can support bindings yourself if you like (though in order to bind to
    them in IB, you need to make a palette, which is often a
    disproportionate amount of work for simple bindable views).  You can,
    of course, bind things in code instead.

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
  • On Sep 11, 2007, at 5:24 AM, Paul Bruneau wrote:

    > On Sep 11, 2007, at 8:16 AM, H M wrote:
    >
    >>> It seems a little strange that an NSView subclass has IBActions/
    >>> IBOutlets... yet the above code seems to imply that.
    >>
    >> hm, come to think of it, i'd say you're right, they should be in a
    >> controller class. that means i have to access the variables using
    >> accessor methods, but that shouldn't be a problem. the question
    >> is, how do I get that controller class to update my view?
    >
    > Please excuse me barging in to ask a quick question of someone: I
    > have a subclass of NSView also. It has an IBOutlet for its
    > controller. Is this the correct way to get data from the controller
    > to the view?

    Yeah sorry poorly worded on my part... it isn't that unusual for a
    view to have an outlet to a data source however it is unusual for a
    view to have outlets to other views.

    Normally a controller, even in the case of a data source, is the one
    that tells the view new/what data exists to display, etc.

    -Shawn
  • On Sep 11, 2007, at 5:16 AM, H M wrote:

    >> It seems a little strange that an NSView subclass has IBActions/
    >> IBOutlets... yet the above code seems to imply that.
    >
    > hm, come to think of it, i'd say you're right, they should be in a
    > controller class. that means i have to access the variables using
    > accessor methods, but that shouldn't be a problem. the question is,
    > how do I get that controller class to update my view?
    >
    >> Can you please outline which classes contain which methods and
    >> which is the NSView subclass? Also can you describe how they are
    >> connected / instantiated in the nib?
    >
    > the NSView subclass is called Sky, and it contains the 3 action
    > methods, the 3 outlets, drawRect: and all the necessary variables,
    > mostly double.
    > in InterfaceBuilder I subclassed NSView, renamed the new class,
    > added the outlets and the actions, then I instantiated it and
    > connected the sliders to their methods and outlets. after that, i
    > created the files and went back to xcode.

    When you say you instantiated it... I assume you mean you dragged an
    NSView off of the palette and into the nib object window (the one
    with the "Instances, Classes, etc. " tabs at the top). If so then you
    created a view that isn't a member of a view hierarchy yet. To "see"
    this view you would need to programmatically add into a view
    hierarchy of a window.

    I also assume you dragged and dropped an NSView off of the palette
    and into an instance of NSWindow. This is the one you see working
    when you resize, etc. This is another instance of your custom view.
    You could connect the actions of your sliders to this instance by
    control dragging from the buttons and to this instance.

    If you are using actions in your view consider making them more data
    source like in naming... for example NSControl has IBActions name
    like the following "takeXxxxValueFrom:".

    -Shawn
  • > When you say you instantiated it... I assume you mean you dragged
    > an NSView off of the palette and into the nib object window (the
    > one with the "Instances, Classes, etc. " tabs at the top). If so
    > then you created a view that isn't a member of a view hierarchy
    > yet. To "see" this view you would need to programmatically add into
    > a view hierarchy of a window.

    negative. by "instantiate" I mean I selected my custom class, then
    chose "instantiate" from the menu.

    > I also assume you dragged and dropped an NSView off of the palette
    > and into an instance of NSWindow. This is the one you see working
    > when you resize, etc.

    affirmative. I forgot to mention that I also selected this view, then
    went to the inspector window, selected custom class and set it to my
    custom class.

    > This is another instance of your custom view. You could connect the
    > actions of your sliders to this instance by control dragging from
    > the buttons and to this instance.

    connect the sliders directly to the view? hmmm... gotta try that...

    --
    GPG Key ID: 92AD877F7E4E32B9
    Fingerprint: 16B0 7DCD 3AB0 0C45 F5FD  581D 92AD 877F 7E4E 32B9
  • >> This is another instance of your custom view. You could connect
    >> the actions of your sliders to this instance by control dragging
    >> from the buttons and to this instance.
    >
    > connect the sliders directly to the view? hmmm... gotta try that...

    it works. YABBADABBADOO! thanks for the help.
    Now I can start working on the other things that don't work right. i
    guess the debugger is gonna be busy...
  • On 9/11/07, H M <hmiersch...> wrote:
    >> When you say you instantiated it... I assume you mean you dragged
    >> an NSView off of the palette and into the nib object window (the
    >> one with the "Instances, Classes, etc. " tabs at the top). If so
    >> then you created a view that isn't a member of a view hierarchy
    >> yet. To "see" this view you would need to programmatically add into
    >> a view hierarchy of a window.
    >
    > negative. by "instantiate" I mean I selected my custom class, then
    > chose "instantiate" from the menu.

    Which results in the same stand alone instance.

    OK so now have it figured out. :)

    -Shawn
  • > It seems a little strange that an NSView subclass has IBActions/
    > IBOutlets... yet the above code seems to imply that.

    I can put those actions into a controller class (already there) but
    then how do I send a setNeedsDisplay message to my view?

    The custom class is called Sky, so I tried [Sky setNeedsDisplay:YES],
    and when I built the project, I got a warning: "Sky might not respond
    to setNeedsDisplay" or something along those lines.

    --
    GPG Key ID: 92AD877F7E4E32B9
    Fingerprint: 16B0 7DCD 3AB0 0C45 F5FD  581D 92AD 877F 7E4E 32B9
  • On 9/13/07, H M <hmiersch...> wrote:
    >> It seems a little strange that an NSView subclass has IBActions/
    >> IBOutlets... yet the above code seems to imply that.
    >
    > I can put those actions into a controller class (already there) but
    > then how do I send a setNeedsDisplay message to my view?
    >
    > The custom class is called Sky, so I tried [Sky setNeedsDisplay:YES],
    > and when I built the project, I got a warning: "Sky might not respond
    > to setNeedsDisplay" or something along those lines.

    Your controller class needs an ivar (instance variable) that points at
    your view (or a way to get a reference to the view). Likely your ivar
    would be an IBOutlet that you could then control-drag from your
    controller object and connect to your view object in the nib.

    -Shawn
  • On 9/13/07, H M <hmiersch...> wrote:

    > The custom class is called Sky, so I tried [Sky setNeedsDisplay:YES],
    > and when I built the project, I got a warning: "Sky might not respond
    > to setNeedsDisplay" or something along those lines.

    The compiler is correct to warn since setNeedsDisplay: is an instance
    method (-[NSView setNeedsDisplay:]) and not a class method.

    -Shawn
previous month september 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Go to today