Using NSProgressIndicator inside an NSMenuItem
Asked Answered
O

3

7

I'm trying to use a NSProgressIndicator (indeterminate) inside of a statusbar-menu. I'm using an NSView-object as view for the menuitem, and then subviews the progress indicator to display it. But whenever i try to call the startAnimation: for the progress, nothing happens. When i try do the very same thing on a normal NSWindow it works perfectly, just not when inside a menuitem.

I'm new to both cocoa and objective-c so I might've overlooked something "obvious" but I've searched quite a bit for a workaround but without success. I found something about menuitems cant be updated while shown and that you need to use a bordeless window instead. But I have not been able to confirm this in any documentation.

Edit:

Ok, almost works now. When using the setUsesThreadedAnimation: and from a MenuDelegate's menuWillOpen and creating a new thread. This thread runs a local method:

-(void) doWork(NSProgressIndicator*) p{
     [p startAnimation:self];
}

This will start the progressindicator on a random(?) basis when opening the menu. If I call startAnimation: directly without going through doWork: (still using a new thread), it never works. Doesn't setUsesThreadedAnimation: make the progress-bar create it's own thread for the animation?

Osber answered 12/1, 2011 at 16:11 Comment(0)
O
16

Solved it by using:

[progressIndicator performSelector:@selector(startAnimation:)
                            withObject:self
                            afterDelay:0.0
                               inModes:[NSArray 
                       arrayWithObject:NSEventTrackingRunLoopMode]];

Inside the menuWillOpen:, the problem seems to have been calling startAnimation: before the progressbar was finished drawing itself.

Osber answered 14/1, 2011 at 14:40 Comment(2)
Crazy how long I've been searching to make this work, thanks a lot!Rorie
it seems even this does not help on High Sierra, although works fine on Sierra and bellow (may be related to this forums.developer.apple.com/thread/83186)Bless
H
1

How are you referencing the NSProgressIndicator that is in the view (and the one in the window, for that matter)? For example, do you have a controller class that has IBOutlet's hooked up to the progress indicators? If you are using an IBOutlet, are you sure it's hooked up properly in the nib file?

Also, where and when are you calling startAnimation:? (We need to see some code).

One thing that can sometimes happen is that you forget to hook up an IBOutlet in the nib. Then, when you attempt to tell the object to do something in code at runtime, the IBOutlet is nil, and so what you think is a message being sent to your object is in fact, a message being sent to nil. In other words, it's just ignored, and effectively looks like it's not working.

Provided you do have a (potentially) valid reference to the UI object, the other common issue you'll see is when a developer is trying to send a message to the object at "too early" of a time. In general, init methods are too early in the controller object's lifetime to be able to send messages to user interface objects—those IBOutlet's are still nil. By the time -awakeFromNib is called, IBOutlet's should be valid (provided you hooked them up in IB) and you can then send the message to the UI object.

Haitian answered 12/1, 2011 at 21:26 Comment(3)
Good points, that explains why i sometimes did have nil-values when trying to reach outlet-components (calling them too early). Now I've seemed to narrow it down to a drawing problem. I've made it animate when the menuitem containing the view is highlighted (in my view's drawRect:), and then make it stop when it's no longer highlighted. But if i try to make it animate outside of the if-clause that checks if the item is highlighted nothing happens (still inside drawRect:).Osber
I've managed to get it working somewhat more, it seems like i had to send stopAnimation: sometime before to make startAnimation: work. But i want it to animate (or not) when they menu is displayed. Currently i have to mouse-over the view for it to start, when they menu is displayed it just shows the progressbar not animating even though it should be hidden when not (setDisplayWhenStopped:NO). To be continued in next comment...Osber
And i still can't get it to work when calling it from outside my view-object, e.g. navigating through subviews of the NSMenu in it's controller class. It seems like there has to be some sort of event when the menu is being displayed for the animation to work.Osber
S
0

Have you told it to use threaded animation via -setUsesThreadedAnimation:?

Sverige answered 12/1, 2011 at 20:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.