 |
 |
Animating NSBezierPath inside an NSView
|
 |
|
 |
|
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status:
Offline
|
|
I have a method that plots a mathematical function inside an NSView.
I would like to see the plot rendering in slow motion. So I figured I just make the main thread sleep for some time before drawing the next point.
The problem is, that NSView does not update itself as I intended. Instead it just waits until it has the complete plot and renders in one shot.
Code:
for(i=1; i<plotLimit; i++){
// some other code
[NSBezierPath strokeLineFromPoint: priorP toPoint:nextP];
// sleep for a little while
}
I guess, I'm not uderstanding how NSView renders. Any tips, ideas?
Thanks in advance.

|
|
|
| |
|
|
|
 |
|
 |
|
Addicted to MacNN
Join Date: Nov 2002
Location: Seattle, WA
Status:
Offline
|
|
I've found that my views update themselves if I call MoviesTask(). it as args too, but I forget what they are. it's in Movies.h
edit: but I think the right way to do it is call -display on your view
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status:
Offline
|
|
I tried using [self display] inside "stepAnimation" but it crashes the app. If instead, I use
[self setNeedsDisplay: YES]; then at least the method's "for loop" is entered (see code below) but the old behaviour persists; namely, that NSView does not animate the plot it just waits until it has a enough info and then displays "a" plot in one shot.
So the animation never takes place... Furthermore, the resulting plot is totally wacked. This is odd becuase a single call to "drawPlot" works great.
Below is all the relevant code. I just don't know what's up...
Code:
- (void)drawRect: (NSRect)rect
{
// Lots of code around here but
// it's not relevant to this discussion
// The next message to self works fine
// it plots the data until a limit is reached
// [self drawPlot:15];
// This one fails
[self stepAnimation:15];
}
- (void)stepAnimation: (int) plotLimit
{
int animationStepCounter;
int c = 0; // for debugging
NSLog(@"Before loop, count = %d", c); // for debugging
for( animationStepCounter=0 ; animationStepCounter < plotLimit ; animationStepCounter++ )
{
[self drawPlot:animationStepCounter];
[self setNeedsDisplay: YES];
sleep(1); // sleeps for one second
NSLog(@"Inside loop, count = %d", c); // for debugging
c++; // for debugging
}
}
// this method is included for completeness, it works fine when called once.
- (void) drawPlot: (int) plotLimit
{
int i;
NSPoint priorP = NSMakePoint( x[0] + originXOffset , Fx[0] + originYOffset );
NSPoint nextP;
for(i=1; i < plotLimit; i++){
Fx[i] = fx[i] * ( diagonal.y - right.y) / 100;
x[i] = x[i] * ( right.x - left.x) / 100;
nextP = NSMakePoint( x[i] + originXOffset , Fx[i] + originYOffset );
[plotColor set];
[NSBezierPath strokeLineFromPoint: priorP toPoint:nextP];
priorP = nextP;
}
}
(Last edited by DaGuy; Jul 23, 2003 at 12:27 PM.
)
|
|
|
| |
|
|
|
 |
|
 |
|
Addicted to MacNN
Join Date: Nov 2002
Location: Seattle, WA
Status:
Offline
|
|
what about MoviesTask() and what if you call -display on the window?
also is this in the main thread? what if you run it in another thread?
|
|
|
| |
|
|
|
 |
|
 |
|
Mac Elite
Join Date: Jan 2001
Location: New York
Status:
Offline
|
|
You need to call setNeedsDisplay:YES every iteration of the loop.
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status:
Offline
|
|
Originally posted by davecom:
You need to call setNeedsDisplay:YES every iteration of the loop.
Thanks. Unless I misunderstood you, I believe I'm already doing that.
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status:
Offline
|
|
Originally posted by Uncle Skeleton:
what about MoviesTask() and what if you call -display on the window?
Thanks for the message. Well, I lost track of the MoviesTask() tip. This is part of the QT API right? I never seen this within Cocoa so I'll probably have to work a little harder and find some examples.
and what if you call -display on the window?
If I do, then the for-loop in stepAnimation method is not entered. All I get it's lots of calls to the method but the for-loop never executes and the app eventually crashes. I get "exited due to signal 11 (SIGSEGV)."
(Last edited by DaGuy; Jul 23, 2003 at 02:24 PM.
)
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Nov 2001
Location: State of Denial
Status:
Offline
|
|
Okay. AFAIK, setNeedsDisplay:YES tells the view to update on the next iteration of the run loop, meaning that it will not do what you're wanting if you call it multiple times in one iteration (for example, in the body of a for loop). Maybe try using an NSTimer that updates every second or half-second that adds a new point to the NSBezierPath and then calls setNeedsDisplay:YES? That way, the view should update the way you want it to...
|
|
[Wevah setPostCount:[Wevah postCount] + 1];
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status:
Offline
|
|
Originally posted by Wevah:
Okay. AFAIK, setNeedsDisplay:YES tells the view to update on the next iteration of the run loop, meaning that it will not do what you're wanting if you call it multiple times in one iteration (for example, in the body of a for loop). Maybe try using an NSTimer that updates every second or half-second that adds a new point to the NSBezierPath and then calls setNeedsDisplay:YES? That way, the view should update the way you want it to...
BINGO! I got some form of animation going. It's not what I wanted but at least I seem to be using [self setNeedsDisplay:YES] correctly which I wasn't before.
The problem I have now is that the resulting drawings are all over the place. But that's something I can probably hammer out on my own.
In any event thanks very much to all that assissted.

(Last edited by DaGuy; Jul 24, 2003 at 12:31 AM.
)
|
|
|
| |
|
|
|
 |
 |
|
 |
|
|
|
|
|

|
|
 |
Forum Rules
|
 |
 |
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is Off
|
|
|
|
|
|
 |
 |
 |
 |
|
 |
|