非脏视图被重绘

发布于 2024-12-07 14:06:15 字数 2955 浏览 0 评论 0原文

我确实有一个奇怪的问题。我编写了一个码头视图。

它基本上是一个 NSView,内部有三个垂直子视图。所以我有一个左侧停靠栏、一个中间视图和一个右侧停靠栏。两个底座都是可折叠的。中间视图在折叠时会调整大小。

我正在使用 CoreAnimation 来制作折叠过程的动画。这几乎是正确的。 如果我展开左侧停靠栏,则会调用右侧停靠栏 drawRect 方法,尽管它并不脏。

如果我停用动画器并直接设置新的帧大小,则右侧停靠栏在展开时不会重绘,因此我认为帧的计算是正确的。

这是我用于折叠码头的代码:

- (void) mouseDown:(NSEvent *)event 
{
  // Exit method if already animating a dock
  if(is_animating)
  {
    return;
  }

  NSPoint firstPoint    = [self convertPoint:[event locationInWindow] fromView:nil];
  unsigned long divider = [self mousePointInCollapseRect:firstPoint];

  // If not clicked on a divider don't animate anything
  if(divider == NSNotFound)
  {
    return;
  }

  NSView* main_view     = [[self subviews] objectAtIndex:VIEW_MIDDLE];
  NSView* collapse_view = [[self subviews] objectAtIndex:(divider == 0)? VIEW_LEFT : VIEW_RIGHT];

  NSRect cframe = [collapse_view frame];  // New collapsable frame
  NSRect mframe = [main_view frame];      // New main frame

  if([self isSubviewCollapsed:collapse_view] == NO)
  {
    if(divider == 0)
    {            
      cframe.size.width  = 0.0;
      mframe.origin.x   -= (dock_width_left + DIVIDER_THICKNESS);
      mframe.size.width += (dock_width_left + DIVIDER_THICKNESS);
    }
    else
    {      
      mframe.size.width += (collapse_view.frame.size.width + DIVIDER_THICKNESS);
      cframe.size.width  = 0.0;
      cframe.origin.x    = mframe.origin.x + mframe.size.width;
    }

    // Turn off autoresizesSubviews on the collapsible subview
    [collapse_view setAutoresizesSubviews:NO];

    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:(ANIMATION_DURATION)]; 

    [[collapse_view animator] setFrame:cframe];
    [[main_view animator]     setFrame:mframe];

    [NSAnimationContext endGrouping];
  }
  else
  {
    // Uncollapse dock    
    if(divider == 0)
    {
      // Left dock
      cframe.size.width  = dock_width_left;
      mframe.origin.x    = (COLLAPSEBAR_THICKNESS + dock_width_left + DIVIDER_THICKNESS);
      mframe.size.width -= (dock_width_left + DIVIDER_THICKNESS);
    }
    else
    {   
      // Right dock
      mframe.size.width -= (dock_width_right + DIVIDER_THICKNESS);
      cframe.size.width  = dock_width_right;
      cframe.origin.x    = mframe.origin.x + mframe.size.width + DIVIDER_THICKNESS;
    }

    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:ANIMATION_DURATION];   

    [[main_view animator]     setFrame:mframe];
    [[collapse_view animator] setFrame:cframe];

    [NSAnimationContext endGrouping];

    //Restore Autoresizing on subview
    [self performSelector:@selector(restoreAutoResizingOfSubview:) withObject:collapse_view afterDelay:ANIMATION_DURATION + 0.05];
  }

  is_animating = YES;
  [self performSelector:@selector(animationEnded) withObject:nil afterDelay:ANIMATION_DURATION + 0.05];
}

那么为什么要重绘非脏视图呢?

I do have a strange problem. I programmed a a dockview.

It's basically a NSView with three vertical subviews inside. So I have a left dock, a middle view and a right dock. Both docks are collapsable. The middle view gets resized while collapsing.

I'm using CoreAnimation to animate the collapsing process. This works almost correct.
If I uncollapse the left dock, the right docks drawRect method gets called although it's not dirty.

If I deactivate the animator and set the new frame size directly, the right dock not gets redrawn while uncollapsing so I assume the calculation of the frames is correct.

Here is my code for collapsing the docks:

- (void) mouseDown:(NSEvent *)event 
{
  // Exit method if already animating a dock
  if(is_animating)
  {
    return;
  }

  NSPoint firstPoint    = [self convertPoint:[event locationInWindow] fromView:nil];
  unsigned long divider = [self mousePointInCollapseRect:firstPoint];

  // If not clicked on a divider don't animate anything
  if(divider == NSNotFound)
  {
    return;
  }

  NSView* main_view     = [[self subviews] objectAtIndex:VIEW_MIDDLE];
  NSView* collapse_view = [[self subviews] objectAtIndex:(divider == 0)? VIEW_LEFT : VIEW_RIGHT];

  NSRect cframe = [collapse_view frame];  // New collapsable frame
  NSRect mframe = [main_view frame];      // New main frame

  if([self isSubviewCollapsed:collapse_view] == NO)
  {
    if(divider == 0)
    {            
      cframe.size.width  = 0.0;
      mframe.origin.x   -= (dock_width_left + DIVIDER_THICKNESS);
      mframe.size.width += (dock_width_left + DIVIDER_THICKNESS);
    }
    else
    {      
      mframe.size.width += (collapse_view.frame.size.width + DIVIDER_THICKNESS);
      cframe.size.width  = 0.0;
      cframe.origin.x    = mframe.origin.x + mframe.size.width;
    }

    // Turn off autoresizesSubviews on the collapsible subview
    [collapse_view setAutoresizesSubviews:NO];

    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:(ANIMATION_DURATION)]; 

    [[collapse_view animator] setFrame:cframe];
    [[main_view animator]     setFrame:mframe];

    [NSAnimationContext endGrouping];
  }
  else
  {
    // Uncollapse dock    
    if(divider == 0)
    {
      // Left dock
      cframe.size.width  = dock_width_left;
      mframe.origin.x    = (COLLAPSEBAR_THICKNESS + dock_width_left + DIVIDER_THICKNESS);
      mframe.size.width -= (dock_width_left + DIVIDER_THICKNESS);
    }
    else
    {   
      // Right dock
      mframe.size.width -= (dock_width_right + DIVIDER_THICKNESS);
      cframe.size.width  = dock_width_right;
      cframe.origin.x    = mframe.origin.x + mframe.size.width + DIVIDER_THICKNESS;
    }

    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:ANIMATION_DURATION];   

    [[main_view animator]     setFrame:mframe];
    [[collapse_view animator] setFrame:cframe];

    [NSAnimationContext endGrouping];

    //Restore Autoresizing on subview
    [self performSelector:@selector(restoreAutoResizingOfSubview:) withObject:collapse_view afterDelay:ANIMATION_DURATION + 0.05];
  }

  is_animating = YES;
  [self performSelector:@selector(animationEnded) withObject:nil afterDelay:ANIMATION_DURATION + 0.05];
}

So why gets a non-dirty view redrawn?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文