如何将 NSPanel 显示为工作表

发布于 2024-08-05 14:07:44 字数 669 浏览 8 评论 0原文

我正在尝试将 NSPanel 显示为工作表。我天真地按照这些思路做一些事情:

SheetController *sheetController = [[[SheetController alloc]
                                      initWithWindowNibName:@"Sheet"] autorelease];

[[NSApplication sharedApplication] beginSheet:sheetController.window 
                               modalForWindow:self.window
                                modalDelegate:self
                               didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) 
                                  contextInfo:nil];

出于某种我无法理解的原因,这不起作用。当调用这部分代码时,工作表会短暂闪烁(因为 autorelease 消息)。床单永远不会挂在窗户上。

如果有人能指出我在哪里可以找到更多信息,那将非常感激。

I'm trying to show a NSPanel as a sheet. I'm naively doing something along those lines:

SheetController *sheetController = [[[SheetController alloc]
                                      initWithWindowNibName:@"Sheet"] autorelease];

[[NSApplication sharedApplication] beginSheet:sheetController.window 
                               modalForWindow:self.window
                                modalDelegate:self
                               didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) 
                                  contextInfo:nil];

For some reason that eludes me, this isn't working. When this part of the code is called, the sheet momentarily flashes (because of the autorelease message). The sheet is never hooked to window.

If anyone can point me to where I can find more information, that would be very appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

听风吹 2024-08-12 14:07:44

这听起来像是在 IB 中选中面板的“启动时可见”框的经典案例。把它关掉。

This sounds like a classic case of having checked the "Visible at Launch" box for the panel in IB. Turn that off.

绮烟 2024-08-12 14:07:44

是的,只要您希望该控制器继续运行,您就需要拥有它。你不能只是创建它,自动释放它,然后让它消亡——只要你需要它,你就需要保留它。

Yes, you need to own this controller for as long as you want it to continue functioning. You can't just create it, autorelease it, and let it die—you need to hold onto it for as long as you need it.

把时间冻结 2024-08-12 14:07:44

不要忘记,如果您尝试将其作为“模态”工作表运行(即它接管应用程序直到用户关闭它),您将需要推送一个新的运行循环。

您所做的只是显示工作表,然后不推送新的循环,因此操作系统只是显示工作表,发现没有理由保持其运行,因此将其关闭并在下一行恢复执行:

我通常按以下方式执行工作表:

- (id)showPanelModalAgainstWindow: (NSWindow *)window
{
   [[NSApplication sharedApplication] beginSheet: panelToShow
                modalForWindow: window
                modalDelegate: self
                didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
                contextInfo: nil];

   [[NSApplication sharedApplication] runModalForWindow: panelToShow];
   if (m_returnCode == NSCancelButton) return nil;
}


- (void)sheetDidEnd:(NSWindow *)sheet
         returnCode:(int)returnCode
        contextInfo:(void  *)contextInfo
{
    UNUSED(sheet);
    UNUSED(contextInfo);
    m_returnCode = returnCode;
}

然后,在您的接受和/或取消按钮例程中:

- (IBAction)continueButtonClicked:(id)sender
{
    UNUSED(sender);
    [[NSApplication sharedApplication] stopModal];
    [createAccountWizardPanel orderOut: nil];
    [[NSApplication sharedApplication] endSheet: createAccountWizardPanel
                                       returnCode: NSOKButton];

}

我确信有一种稍微少一点的代码方式来执行此操作,但我没有深入研究它,因为这种方式有效到目前为止,一切都很好......

之前关于控制器和面板对象的生命周期的评论也是相关的——在显示模式面板时,一定要准确理解您需要什么生命周期的对象。

Don't forget that if you're trying to run this as a "modal" sheet (i.e. it takes over the app until the user dismisses it), you'll need to push a new run loop.

What you've done is shown the sheet, and then not pushed a new loop, so the OS just shows the sheet, sees there's no reason to keep it running, and thus shuts it down and resumes execution on the next line:

I typically do sheets the following way:

- (id)showPanelModalAgainstWindow: (NSWindow *)window
{
   [[NSApplication sharedApplication] beginSheet: panelToShow
                modalForWindow: window
                modalDelegate: self
                didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:)
                contextInfo: nil];

   [[NSApplication sharedApplication] runModalForWindow: panelToShow];
   if (m_returnCode == NSCancelButton) return nil;
}


- (void)sheetDidEnd:(NSWindow *)sheet
         returnCode:(int)returnCode
        contextInfo:(void  *)contextInfo
{
    UNUSED(sheet);
    UNUSED(contextInfo);
    m_returnCode = returnCode;
}

Then, in your accept and/or cancel button routines:

- (IBAction)continueButtonClicked:(id)sender
{
    UNUSED(sender);
    [[NSApplication sharedApplication] stopModal];
    [createAccountWizardPanel orderOut: nil];
    [[NSApplication sharedApplication] endSheet: createAccountWizardPanel
                                       returnCode: NSOKButton];

}

I'm sure there is a slightly less code-y way of doing this, but I've not looked to deeply into it, because this way works perfectly fine thus far ....

Previous comments about the lifetime of the controller and panel objects are also relevant -- be sure to understand exactly what objects you need for what lifetimes when showing a modal panel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文