NSMenuItem中的动画进度条 [英] Animated progress bar in NSMenuItem

查看:189
本文介绍了NSMenuItem中的动画进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 NSMenuItem 自定义视图中放置一个动画进度条。这在苹果的 MenuItemView 示例中已经说明,但是它没有动画(至少不是在10.5中,示例显然来自10.4)。



我试着设置一个定时器调用 setNeedsDisplay:YES ,计划为 NSEventTrackingRunLoopMode 像文档说。这个工作,但只有一个确定的进度条,如果我改变的值,只有第一次菜单打开。第二次和连续的时间,酒吧重画两次,然后保持冻结。对于不确定的进度条,理发师杆条从不动画。





编辑:代码段。我只是添加了 itemChanged 调用,这似乎没有任何效果。更新纯文字项目的效果很好。

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

def applicationDidFinishLaunching_(self,sender):
statusbar = NSStatusBar.systemStatusBar()
self.statusitem = statusbar.statusItemWithLength_ b $ b 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_(真)
itemView.addSubview_(AppDelegate.menuProgressBar)
AppDelegate.menuProgressBar.setIndeterminate_(假)
的AppDelegate .menuProgressBar.setMaxValue_(100)
AppDelegate.menuProgressBar.startAnimation_(个体经营)
定时器= NSTimer.timerWithTimeInterval_target_selector_userInfo_repeats_(
0.1,自我,
objc.selector(self.animateProgress,签名='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)

高清animateProgress(个体经营):
时间= NSDate.timeIntervalSinceReferenceDate()
AppDelegate.menuProgressBar.setDoubleValue_(时间%100)
AppDelegate.menuProgressBar.display()
的AppDelegate .progressItem.setTitle _('Progress:%d'%(time%100))
AppDelegate.barItem.menu()。itemChanged_(AppDelegate.barItem)
   - (void)menuWillOpen:(NSMenu *)menu 
{
[[progressIndicator performSelector:@selector(startAnimation :)
withObject:self
afterDelay:0.0
inModes:[NSArray arrayWithObject:NSEventTrackingRunLoopMode]];
}

对于确定的指标我试过你的代码(但是在objective-C)有效。我不知道python或PyObjC,但看着时间变量的代码,我想你是发送timeIntervalSinceReferenceDate()调用NSDate类。所以也许时间总是零?基于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 repetes:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode];
}

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


I want to put an animated progress bar in an NSMenuItem custom view. This is demonstrated in Apple's MenuItemView sample, but it doesn't animate (at least not in 10.5, and the sample is apparently from 10.4).

I have tried setting a timer that calls setNeedsDisplay:YES, scheduled as NSEventTrackingRunLoopMode like the docs say. This works, but only for a determinate progress bar if I change the value, and only the first time the menu opens. The second and successive times, the bar redraws twice and then remains frozen. For an indeterminate progress bar, the barber pole stripes never animate.


Edit: code snippet. I just added the itemChanged call, which didn't seem to have any effect. Updating the text-only item works fine.

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)

解决方案

For an indeterminate indicator I send the startAnimation: message in the menu's menuWillOpen: delegate method using performSelector:... to send it in the NSEventTrackingRunLoopMode mode.

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

For the determinate indicator I tried your code (but in objective-C) and it worked. I don't know python or PyObjC but looking at the code for the time variable I think you are sending the timeIntervalSinceReferenceDate() call to the NSDate class. So maybe time is always zero? Based on the alloc() calls I wonder if it shouldn't be ...

time = NSDate.date().timeIntervalSinceReferenceDate()


Update: for the record here is the code I used for testing the determinate progress indicator. Just obj-c version of the OP's code. The indicator updates properly.

- (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)];
}

这篇关于NSMenuItem中的动画进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆