【问题标题】:Dynamically resize NSWindow based on NSOutlineView height根据 NSOutlineView 高度动态调整 NSWindow 大小
【发布时间】:2012-06-08 16:27:26
【问题描述】:

我已经阅读了很多关于动态调整 NSWindows 大小的问题的答案,但还没有什么效果。

我已经构建了一个类似“弹出框”的窗口以从菜单栏显示,我不能使用 NSPopover,因为它在设计方面不够可定制。我的视图层次结构当前如下所示:

NSWindow Subclass
  - NSView (clears the titlebar rendering, draws popover arrow)
     - NSView (contentView)
        - NSOutlineView (main table of content)
        - NSView (window footer)

我需要的是窗口随着 NSOutlineView 中的项目的扩展和收缩而扩展和收缩,以便窗口始终是大纲视图、页脚和顶部弹出箭头的正确高度。

我有一些方法可以根据内容计算大纲视图所需的高度。到目前为止,我一直在尝试重新计算在内容视图控制器上调用 awakeFromNib 时的大小,然后在委托方法 outlineViewItemDidCollapse:outlineViewItemDidExpand: 上再次计算大小,但我永远无法正确调整窗口大小。

我尝试了很多不同的方法,但都没有奏效。有没有“规范”的方法来做到这一点?我看到人们谈论 -[NSWindow frameForContentRect:] 与这类问题有关,但我不太明白这是怎么回事。

也许我的做法完全错误,但我希望不会。看起来这应该是可能的,它只是在正确的地方得到正确的东西。不幸的是,GUI 编程对我来说不是一个强项。我将不胜感激人们提出的任何想法或解决方案。

谢谢。

编辑:这已解决,部分原因是标记的答案,部分原因是其他一些原因。清除 NSView 没有自动调整大小的掩码,所以我将其设置为向各个方向扩展,这有助于解决一些调整大小的问题。此外,我用于计算所需高度的方法并不完全正确,并且存在一些问题。

根据提供的答案,在某些情况下找到所需高度的方法很好,但我没有可以测量的“根”项目。这可能需要考虑。

【问题讨论】:

    标签: macos cocoa nsview nswindow appkit


    【解决方案1】:

    这是我的方法,效果很好,但可能还有比这更好的方法。

    - (void)outlineViewItemDidExpand:(NSNotification *)notification {
        [self resizeWindowHeight];
    }
    - (void)outlineViewItemDidCollapse:(NSNotification *)notification {
        [self resizeWindowHeight];
    }
    - (void)resizeWindowHeight {
        NSRect wRect = [myWindow frame];
        NSRect oRect = [myoutlineView rectOfRow:([myoutlineView numberOfRows] - 1)]; //get rect of last row
        CGFloat n = oRect.origin.y + oRect.size.height + 22;
        wRect.origin.y = wRect.origin.y + (wRect.size.height - n);
        wRect.size.height = n;
        [myWindow setFrame:wRect display:YES animate:YES];
    }
    

    数字22是:(顶部窗口-顶部大纲)+大纲标题高度+水平滚动条高度+(底部窗口-底部大纲)+工具栏高度的总和

    我在 IB 中的这个例子的设置:没有水平滚动条和没有标题,Outline 的高度 = 窗口的 contentView 的高度,所以 22 是窗口边框。

    如果你有工具栏或者水平滚动条被自动隐藏,你需要在代码中添加条件来检查(工具条和滚动条)的可见性并相应地改变高度。

    【讨论】:

    • 好的,这很棒。我几乎已经完成了所有工作。现在的主要问题是窗口在 NSOutlineView 发生更改之前更改了框架,理想情况下这些需要同步。有什么想法可以做到吗?
    • 我已经通过“dispatch_async”调用setFrame:display:animate: 几乎同步了它。稍作改动就可以了。
    • 好的。它现在工作得很好,但动画的时间不太正确,这意味着有一些我不太喜欢的图形抖动。您对我可以做些什么来阻止这种情况有什么建议吗?
    • 好的,我测试了一个大层次结构(多列)。当我折叠一个项目时,我看到这些项目在调整窗口大小的同时折叠了,当我展开一个项目时我没有问题。所以有了这个,我没有这个问题。 -(void)outlineViewItemDidCollapse:(NSNotification *)notification { [self performSelector:@selector(resizeWindowHeight) withObject:nil afterDelay:0.1]; 不知道是不是和dispatch_async不一样
    • 感谢您的想法,我会尝试的。由于实际问题现已解决,因此我已将此标记为答案,但我会在找到问题时用更多详细信息更新问题。感谢所有的帮助。
    【解决方案2】:

    一种方法是记录轮廓视图的初始高度和窗口的初始高度,然后随着轮廓视图高度的变化,计算窗口的新高度 = 旧高度 + (新轮廓高度 - 旧轮廓高度)。通过仅根据初始状态的更改工作,它使事情变得更加灵活。如果您从头开始重新计算事物的大小,您不必在代码中复制整个布局。您可以使用 IB 对窗口进行布局,它应该保留该布局,而无需代码了解太多细节。并且你可以在 IB 中更新布局,代码仍然有效。

    否则,我建议你展示你所尝试的并解释它是如何不正确的。

    【讨论】:

      猜你喜欢
      • 2021-08-02
      • 2013-06-06
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      • 2023-03-28
      • 2019-09-18
      • 2016-05-12
      • 2013-05-08
      相关资源
      最近更新 更多