5

我正在使用 Pyobjc 创建一个 NSStatusItem。单击它时,我将显示一个 NSPopOver。这工作正常。但是,我的要求是在应用程序启动后立即显示弹出框,而无需用户进行任何操作。直接在 finishLaunching 中调用回调不起作用。有什么办法可以做到这一点?即使可以模拟 NSStatusView 上的点击也足够了。

class TestApp(NSApplication):

    def finishLaunching(self):
        # Make statusbar item
        statusbar = NSStatusBar.systemStatusBar()
        self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength)
        self.statusitem.setTarget_(self)
        self.statusitem.setAction_('statusItemClicked:')
        self.icon = NSImage.alloc().initByReferencingFile_('app-icon.png')
        self.icon.setScalesWhenResized_(True)
        self.icon.setSize_((20, 20))
        self.statusitem.setImage_(self.icon)
        self.statusitem.setHighlightMode_(1)

        # self.statusItemClicked_(None)

    def statusItemClicked_(self, notification):
        self.viewController = SimpleXibDemoController.alloc().initWithWindowNibName_("Login")

        # Show the window
        self.viewController.showWindow_(self.viewController)
        rect = self.statusitem.valueForKey_('button').frame()
        self.viewController.popover.showRelativeToRect_ofView_preferredEdge_(rect, self.statusitem.valueForKey_('button'), NSMaxYEdge)
4

2 回答 2

2

我终于得到了一个有点粗略的解决方案。我有一种方法可以像这样定位弹出框:

- (IBAction)showPopover:(id)sender {
    [popover showRelativeToRect:self.statusItemView.bounds ofView:self.statusItemView preferredEdge:NSMinYEdge];
}

在 applicationDidFinishLaunching 或您的情况下为 finishLaunching 中,我没有直接调用该方法,而是使用 performSelector 调用它:

[self performSelector:@selector(showPopover:) withObject:self afterDelay:0];

即使将延迟设置为 0 也可以,我不知道为什么,它现在可以正确定位弹出框。

编辑:这似乎只在情况下起作用。即使通过创建视图控制器并从 viewDidAppear 调用它,弹出框也只能在一半的时间内定位。

编辑 2:我在状态项的窗口中添加了一个窗口控制器,并覆盖了 windowDidLoad。然而事实证明,在我什至可以设置控制器的窗口之前加载窗口,因此不会调用 windowDidLoad。

于 2014-08-30T14:30:16.767 回答
1

您必须等到视图出现才能呈现NSPopover. viewDidAppear在您的子类中覆盖NSViewController并在那里展示它。loadView(或者如果您的最小部署目标小于 OS X Yosemite,则覆盖。)

于 2014-08-30T14:30:15.547 回答