2010-11-03 77 views
1

我想將動畫進度條放在NSMenuItem自定義視圖中。這在Apple的MenuItemView示例中得到了演示,但它不帶動畫(至少不在10.5中,示例顯然是從10.4開始的)。NSMenuItem中的動畫進度條

我試着設置一個計時器,調用setNeedsDisplay:YES,計劃爲NSEventTrackingRunLoopMode像文檔說的。這是有效的,但只適用於確定的進度條,如果我更改了值,並且僅在菜單第一次打開時纔有效。第二次和連續的時間,酒吧重繪兩次,然後凍結。對於一個不確定的進度條,理髮杆條紋從不動畫。


編輯:代碼片段。我剛剛添加了 itemChanged呼叫,這似乎沒有任何影響。更新純文字項目正常工作。

class AppDelegate(NSObject): 
    barItem = None 
    menuProgressBar = None 
    progressItem = None 

    def applicationDidFinishLaunching_(self, sender): 
    statusbar = NSStatusBar.systemStatusBar() 
    self.statusitem = statusbar.statusItemWithLength_(
     NSSquareStatusItemLength) 
    self.statusitem.setHighlightMode_(True) 
    image = NSImage.imageNamed_("menubar.png") 
    self.statusitem.setImage_(image) 
    self.statusitem.retain() 

    menu = NSMenu.alloc().init() 

    AppDelegate.barItem = NSMenuItem.alloc(). \ 
     initWithTitle_action_keyEquivalent_('progress', None, '') 
    itemView = NSView.alloc().initWithFrame_(NSMakeRect(0, 0, 50, 20)) 
    itemView.setAutoresizingMask_(NSViewWidthSizable) 
    AppDelegate.menuProgressBar = \ 
     NSProgressIndicator.alloc().initWithFrame_(NSMakeRect(16, 5, 22, 10)) 
    AppDelegate.menuProgressBar.setAutoresizingMask_(NSViewWidthSizable) 
    AppDelegate.menuProgressBar.setControlSize_(NSSmallControlSize) 
    AppDelegate.menuProgressBar.setUsesThreadedAnimation_(True) 
    itemView.addSubview_(AppDelegate.menuProgressBar) 
    AppDelegate.menuProgressBar.setIndeterminate_(False) 
    AppDelegate.menuProgressBar.setMaxValue_(100) 
    AppDelegate.menuProgressBar.startAnimation_(self) 
    timer = NSTimer.timerWithTimeInterval_target_selector_userInfo_repeats_(
     0.1, self, 
     objc.selector(self.animateProgress, signature='[email protected]:'), 
     None, True) 
    NSRunLoop.currentRunLoop().addTimer_forMode_(
     timer, NSEventTrackingRunLoopMode) 
    AppDelegate.barItem.setView_(itemView) 
    menu.addItem_(AppDelegate.barItem) 

    AppDelegate.progressItem = NSMenuItem.alloc(). \ 
     initWithTitle_action_keyEquivalent_('Progress', None, '') 
    menu.addItem_(AppDelegate.progressItem) 

    self.statusitem.setMenu_(menu) 

    def animateProgress(self): 
    time = NSDate.timeIntervalSinceReferenceDate() 
    AppDelegate.menuProgressBar.setDoubleValue_(time%100) 
    AppDelegate.menuProgressBar.display() 
    AppDelegate.progressItem.setTitle_('Progress: %d'%(time%100)) 
    AppDelegate.barItem.menu().itemChanged_(AppDelegate.barItem) 

回答

1

定時器的方法應該是完全沒有必要的。你有沒有告訴NSProgressIndicator -setUsesThreadedAnimation:YES然後告訴它到-startAnimation:?

+0

是的,我也做了這些。沒有效果。 – Uncommon 2010-11-03 19:21:31

+0

可能會發布您的代碼的時間。 – 2010-11-03 19:25:00

+0

已發佈代碼示例。 – Uncommon 2010-11-04 20:32:06

1

對於不確定指標,我使用performSelector:...在NSEventTrackingRunLoopMode模式下發送菜單的menuWillOpen:delegate方法中的startAnimation:消息。

- (void)menuWillOpen:(NSMenu *)menu 
{ 
    [[progressIndicator performSelector:@selector(startAnimation:) 
          withObject:self 
          afterDelay:0.0 
           inModes:[NSArray arrayWithObject:NSEventTrackingRunLoopMode]]; 
} 

對於確定性指標,我嘗試了你的代碼(但在Objective-C中),它工作。我不知道python或PyObjC,但看着時間變量的代碼,我認爲你正在發送timeIntervalSinceReferenceDate()調用到NSDate類。所以也許時間總是零?基於該ALLOC()調用我不知道如果它不應該是...

時間= NSDate.date()timeIntervalSinceReferenceDate()


更新:這裏記錄是我用於測試確定進度指示器的代碼。 OP代碼的obj-c版本。指標正確更新。

- (void)menuWillOpen:(NSMenu *)menu 
{ 
    NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(animateProgress:) userInfo:nil repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode]; 
} 

- (void)animateProgress:(NSTimer *)timer 
{ 
    NSTimeInterval time = [[NSDate date] timeIntervalSinceReferenceDate]; 
    [progressIndicator setDoubleValue:fmod(time, 100)]; 
} 
+0

NSDate調用工作正常。確定的進度條在菜單首次打開時起作用,而純文本項始終有效。我會嘗試繼承NSView,這樣我就可以覆蓋menuWillOpen。 – Uncommon 2010-11-05 17:29:45

+0

我的意思是,我會嘗試做代表的事情。 – Uncommon 2010-11-05 17:52:01