【问题标题】:NSPopover transiency when popover is in status bar弹出框在状态栏中时的 NSPopover 瞬态
【发布时间】:2012-02-21 16:17:32
【问题描述】:

我正在制作一个位于状态栏中的应用程序。单击状态项时,会弹出 NSPopover。

看起来像这样:

问题是:我希望它是“瞬态的”,也就是说,如果我点击弹出框之外的任何地方,它就会关闭。虽然当弹出框在窗口中时 NSPopoverBehaviorTransient 可以正常工作,但在状态栏中时它不起作用。

我怎样才能自己实现这种行为?

【问题讨论】:

    标签: cocoa osx-lion statusbar popover nsstatusbar


    【解决方案1】:

    结果很简单:

    - (IBAction)openPopover:(id)sender
    {
        // (open popover)
    
        if(popoverTransiencyMonitor == nil)
        {
            popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask handler:^(NSEvent* event)
                                        {
                                            [self closePopover:sender];
                                        }];
        }
    }
    
    - (IBAction)closePopover:(id)sender
    {
        if(popoverTransiencyMonitor)
        {
            [NSEvent removeMonitor:popoverTransiencyMonitor];
    
            popoverTransiencyMonitor = nil;
        }
    
        // (close popover)
    }
    

    然而,并不容易的是,从 NSStatusItem 弹出一个弹出框存在令人讨厌的问题(当调用任务控制或空间切换到全屏窗口时,它的行为不符合预期)。我必须实现一个始终浮动在 NSStatusItem 上方并处理切换到全屏窗口等的自定义窗口。这看起来很容易,但显然状态项不是为类似的东西设计的;)

    【讨论】:

    • 为了与系统状态项的行为一致:addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask — 这样右键单击也会关闭弹出框。
    【解决方案2】:

    我使用的方法类似于上面的答案,除了我将所有内容组合到一个方法中,而不是使用两个单独的 IBAction。

    首先,我声明以下属性

    @property (strong, nonatomic) NSStatusItem *statusItem;
    @property (strong, nonatomic) NSEvent *popoverTransiencyMonitor;
    @property (weak, nonatomic) IBOutlet NSPopover *popover;
    @property (weak, nonatomic) IBOutlet NSView *popoverView;
    

    然后在 awakeFromNib 中设置状态栏项

    - (void)awakeFromNib {
    
        self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    
        self.statusItem.title = @"Title";
        self.statusItem.highlightMode = YES;
        self.statusItem.action = @selector(itemClicked:);
    }
    

    后跟点击状态栏项时调用的方法

    - (void)itemClicked:(id)sender {
    
        [[self popover] showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];
    
        if (self.popoverTransiencyMonitor == nil) {
            self.popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask | NSRightMouseDownMask | NSKeyUpMask) handler:^(NSEvent* event) {
                [NSEvent removeMonitor:self.popoverTransiencyMonitor];
                self.popoverTransiencyMonitor = nil;
                [self.popover close];
            }];
        }
    }
    

    当用户在视图外点击时,弹出框会出现并关闭。

    请注意,在 Interface Builder 中,您必须将弹出框的行为设置为 Transient,以便在用户单击状态项时弹出框将关闭。

    【讨论】:

      猜你喜欢
      • 2011-11-21
      • 1970-01-01
      • 2012-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多