自定义 NSWindow 内容边距会导致自动调整大小蒙版混乱

发布于 2024-10-20 11:59:27 字数 2695 浏览 2 评论 0原文

我目前正在使用 this 中显示的方法 Cocoa with Love 文章创建自定义 NSWindow 子类。如示例中所示,我需要在窗口内容周围有大约 10 像素的边距才能绘制箭头(我正在创建一个弹出窗口样式窗口)。我必须在整个窗口周围留有边距,而不仅仅是带有箭头的一侧,因为我希望能够更改箭头位置,而不必重新定位内容。

总而言之,我用来执行此操作的方法是(相关代码在底部):

  • 重写 NSWindow 的 contentRectForFrameRect:frameRectForContentRect:styleMask: 方法来添加内容周围的填充:
  • 将窗口的自定义绘制框架视图设置为 contentView,然后重写 contentView 的 setter 和 getter,以便传入的视图添加为框架视图的子视图

问题在于窗口实际内容视图内的视图的自动调整大小蒙版完全混乱。以下是我在界面生成器中设置内容的方式:

Layout

以下是表视图滚动视图的自动调整大小掩码的方式设置为:

Table View Autoresizing

以下是如何设置文本标签的自动调整大小掩码:

Label Autoresizing

这是应用程序内的结果:

“实际结果”

相关代码(源自上述文章)

#define CONTENT_MARGIN 10.0

- (NSRect)contentRectForFrameRect:(NSRect)windowFrame
{
    windowFrame.origin = NSZeroPoint;
    return NSInsetRect(windowFrame, CONTENT_MARGIN, ICONTENT_MARGIN);
}

- (NSRect)frameRectForContentRect:(NSRect)contentRect
{
    return NSInsetRect(contentRect, -CONTENT_MARGINT, -CONTENT_MARGIN);
}

+ (NSRect)frameRectForContentRect:(NSRect)contentRect
                        styleMask:(NSUInteger)windowStyle
{
    return NSInsetRect(contentRect, -CONTENT_MARGIN, -CONTENT_MARGIN);
}


- (NSView*)contentView
{
    return _popoverContentView;
}

- (void)setContentView:(NSView *)aView
{
    if ([_popoverContentView isEqualTo:aView]) { return; }
    NSRect bounds = [self frame];
    bounds.origin = NSZeroPoint;
    SearchPopoverWindowFrame *frameView = [super contentView];
    if (!frameView) {
        frameView = [[[SearchPopoverWindowFrame alloc] initWithFrame:bounds] autorelease];
        [super setContentView:frameView];
    }
    if (_popoverContentView) {
        [_popoverContentView removeFromSuperview];
    }
    _popoverContentView = aView;
    [_popoverContentView setFrame:[self contentRectForFrameRect:bounds]];
    [_popoverContentView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
    [frameView addSubview:_popoverContentView];
}

我认为弹出内容可能以某种方式超出了边缘,所以我在内容视图周围画了一个边框,但是没有,一切都是应该如此。唯一的问题是内容视图内标签和表视图的自动调整大小蒙版无法正常工作。非常感谢任何建议。

编辑:如果有人感兴趣,我已经在 github 上开源了这个弹出窗口/控制器的完整代码 INPopoverController。包含一个示例项目,以防您想尝试重现该问题。

I'm currently using the method shown in this Cocoa with Love article to create a custom NSWindow subclass. As in the example, I needed to have a roughly 10px margin around the content of the window in order to draw an arrow (I'm creating a popover style window). I had to have the margin around the entire window instead of just the side with the arrow on it because I wanted to be able to change the arrow position without having to reposition the content.

To summarize, the method I'm using to do this is (relevant code is at the bottom):

  • Override the contentRectForFrameRect: and frameRectForContentRect:styleMask: methods of NSWindow to add the padding around the content:
  • Sets the custom drawn frame view of the window as the contentView and then overrides the setter and getter for the contentView so that the view that is passed in is added as a subview of the frame view.

The problem is that the autoresizing masks of views inside the actual content view of the window are completely messed up. Here is how I'm setting up the content in interface builder:

Layout

Here's how the autoresizing mask of the table view scroll view is set up:

Table View Autoresizing

And here's how the text label's autoresizing mask is set:

Label Autoresizing

And here's what the result looks like in-app:

Actual result

Relevant code (derived from the aforementioned article)

#define CONTENT_MARGIN 10.0

- (NSRect)contentRectForFrameRect:(NSRect)windowFrame
{
    windowFrame.origin = NSZeroPoint;
    return NSInsetRect(windowFrame, CONTENT_MARGIN, ICONTENT_MARGIN);
}

- (NSRect)frameRectForContentRect:(NSRect)contentRect
{
    return NSInsetRect(contentRect, -CONTENT_MARGINT, -CONTENT_MARGIN);
}

+ (NSRect)frameRectForContentRect:(NSRect)contentRect
                        styleMask:(NSUInteger)windowStyle
{
    return NSInsetRect(contentRect, -CONTENT_MARGIN, -CONTENT_MARGIN);
}


- (NSView*)contentView
{
    return _popoverContentView;
}

- (void)setContentView:(NSView *)aView
{
    if ([_popoverContentView isEqualTo:aView]) { return; }
    NSRect bounds = [self frame];
    bounds.origin = NSZeroPoint;
    SearchPopoverWindowFrame *frameView = [super contentView];
    if (!frameView) {
        frameView = [[[SearchPopoverWindowFrame alloc] initWithFrame:bounds] autorelease];
        [super setContentView:frameView];
    }
    if (_popoverContentView) {
        [_popoverContentView removeFromSuperview];
    }
    _popoverContentView = aView;
    [_popoverContentView setFrame:[self contentRectForFrameRect:bounds]];
    [_popoverContentView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
    [frameView addSubview:_popoverContentView];
}

I thought that maybe the popover content was going over the margins somehow, so I drew a border around the content view, but no, everything is as should be. The only issue is that the autoresizing masks of the label and table view inside the content view do not work as they should. Any advice is greatly appreciated.

EDIT: If anyone's interested, I've open-sourced the complete code for this popover window/controller on github as INPopoverController. Includes a sample project in case you want to try and reproduce the issue.

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

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

发布评论

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

评论(1

鱼忆七猫命九 2024-10-27 11:59:27
-( void )scaleWindowForHeight:( float )height
{
    if (height > 22)
    {
        NSWindow* window = [self window];
        NSRect old_window_frame = [window frame];
        NSRect old_content_rect = [window contentRectForFrameRect: old_window_frame];
        NSSize new_content_size = NSMakeSize( old_window_frame.size.width, height );
        // need to move window by Y-axis because NSWindow origin point is at lower side:
        NSRect new_content_rect = NSMakeRect( NSMinX( old_content_rect ), NSMaxY( old_content_rect ) - new_content_size.height, new_content_size.width, new_content_size.height );
        NSRect new_window_frame = [window frameRectForContentRect: new_content_rect];
        [window setFrame: new_window_frame  display:YES  animate: [window isVisible] ];
    }
    else
        NSLog(@"window size too small");
}
-( void )scaleWindowForHeight:( float )height
{
    if (height > 22)
    {
        NSWindow* window = [self window];
        NSRect old_window_frame = [window frame];
        NSRect old_content_rect = [window contentRectForFrameRect: old_window_frame];
        NSSize new_content_size = NSMakeSize( old_window_frame.size.width, height );
        // need to move window by Y-axis because NSWindow origin point is at lower side:
        NSRect new_content_rect = NSMakeRect( NSMinX( old_content_rect ), NSMaxY( old_content_rect ) - new_content_size.height, new_content_size.width, new_content_size.height );
        NSRect new_window_frame = [window frameRectForContentRect: new_content_rect];
        [window setFrame: new_window_frame  display:YES  animate: [window isVisible] ];
    }
    else
        NSLog(@"window size too small");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文