1

NSMenuItemカスタム ビューにアニメーション プログレス バーを配置したいと考えています。これは Apple のMenuItemViewサンプルで示されていますが、アニメーション化されません (少なくとも 10.5 ではなく、サンプルは明らかに 10.4 のものです)。

ドキュメントのようsetNeedsDisplay:YESにスケジュールされた を呼び出すタイマーを設定しようとしました。NSEventTrackingRunLoopModeこれは機能しますが、値を変更した場合の確定的な進行状況バーに対してのみ、メニューが初めて開いたときのみです。2 回目以降は、バーが 2 回再描画され、その後は固定されたままになります。不確定なプログレス バーの場合、バーバー ポール ストライプはアニメーション化されません。


編集:コードスニペット。呼び出しを追加しただけ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='v@:'),
        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)
4

2 に答える 2

1

タイマーのアプローチは完全に不要です。NSProgressIndicator に -setUsesThreadedAnimation:YES を指定してから -startAnimation: を指定しましたか?

于 2010-11-03T18:14:39.833 に答える
1

不確定インジケータの場合、メニューの menuWillOpen: デリゲート メソッドで startAnimation: メッセージを送信し、 performSelector:... を使用して NSEventTrackingRunLoopMode モードで送信します。

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

確定指標については、あなたのコードを試してみましたが (しかし、objective-C で)、うまくいきました。私はpythonまたはPyObjCを知りませんが、時間変数のコードを見ると、NSDateクラスに timeIntervalSinceReferenceDate() 呼び出しを送信していると思います。では、時間は常にゼロなのでしょうか? alloc() 呼び出しに基づいて、そうすべきではないのだろうか...

time = 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)];
}
于 2010-11-05T03:42:47.607 に答える