NSWindow - 無邊框,透明窗口 - 動畫窗口高度時閃爍的陰影

[英]NSWindow - borderless, transparent window - flickering shadow when animating window height


Here's another NSWindow question ... I've got borderless window, transparent, which is created in this way ...

這是另一個NSWindow問題......我有無邊框窗口,透明,這是以這種方式創建的......

- (id)initWithView:(NSView *)view anchorPoint:(NSPoint)anchorPoint position:(NSPoint)position distance:(CGFloat)distance {
  if ( !view ) {
    return nil;
  }

  NSSize size = view.intrinsicContentSize;
  NSRect contentRect = NSMakeRect( 0, 0, size.width, size.height );

  self = [super initWithContentRect:contentRect
                          styleMask:NSBorderlessWindowMask
                            backing:NSBackingStoreBuffered
                              defer:NO];

  if ( !self ) {
    return nil;
  }

  _windowView = view;
  _anchorPoint = anchorPoint;
  _position = position;
  _distance = distance;

  [self setContentView:_windowView];

  [self setExcludedFromWindowsMenu:YES];
  [self setMovableByWindowBackground:NO];

  [self setOpaque:NO];
  [self setBackgroundColor:[NSColor clearColor]];

  [self setHasShadow:YES];
  [self useOptimizedDrawing:YES];

  [self setReleasedWhenClosed:NO];

  [self setFrame:[self windowRectWithSize:contentRect.size] display:YES];

  [self setAnchorAttribute:NSLayoutAttributeTop forOrientation:NSLayoutConstraintOrientationVertical];
  [self setAnchorAttribute:NSLayoutAttributeCenterX forOrientation:NSLayoutConstraintOrientationHorizontal];

  [[NSNotificationCenter defaultCenter] addObserver:self
                                           selector:@selector(viewFrameDidChange:)
                                               name:NSViewFrameDidChangeNotification
                                             object:nil];

  return self;
}

... and viewFrameDidChange: is defined as ...

...和viewFrameDidChange:定義為......

- (void)viewFrameDidChange:(NSNotification *)note {
  if ( note.object != self.contentView ) {
    return;
  }

  [self display];
  [self setHasShadow:NO];
  [self setHasShadow:YES];
}

... this is the only way to have proper NSWindow shadow. In other words, whenever window size changes, I have to call display, setHasShadow:NO and setHasShadow:YES otherwise the window shadow is crippled - it's not around the whole window - just part of the window, etc.

......這是獲得適當的NSWindow陰影的唯一方法。換句話說,每當窗口大小改變時,我必須調用display,setHasShadow:NO和setHasShadow:YES否則窗口陰影被削弱 - 它不在整個窗口周圍 - 只是窗口的一部分,等等。

This does work until I start animating height. If height is animated, shadow is correctly recalculated and displayed, but the whole window & shadow is flickering and it's pretty ugly.

這確實有效,直到我開始設置動畫高度。如果高度是動畫的,陰影會被正確重新計算並顯示,但整個窗口和陰影都會閃爍,而且非常難看。

An idea why the shadow is flickering? I tried to replace display, setHasShadow:NO/YES with [self invalidateShadow], but it doesn't work at all and shadow is displayed in a wrong way.

一個想法為什么陰影閃爍?我嘗試用[self invalidateShadow]替換display,setHasShadow:NO / YES,但它根本不起作用,陰影以錯誤的方式顯示。

How one should animate window height with shadow in borderless/transparent window to avoid flickering?

如何在無邊框/透明窗口中使用陰影設置窗口高度動畫以避免閃爍?

Here's the video of the flickering shadow. http://d.pr/v/lbkQ

這是閃爍陰影的視頻。 http://d.pr/v/lbkQ

2 个解决方案

#1


2  

The shadow calculation and drawing is a very resource-consuming operation. So I wouldn't recommend you to invalidate and recalculate the shadow each time the frame changes. Besides, NSWindowDelegate has a –windowDidResize: method, so why using observer?

陰影計算和繪圖是一項非常耗費資源的操作。因此,我建議您不要在每次幀更改時使影子無效並重新計算。此外,NSWindowDelegate有一個-windowDidResize:方法,為什么要使用觀察者呢?

  1. How do you get your window resized? Maybe adding NSResizableWindowMask to the window's style mask will do the trick? You should give it a try.

    你如何調整窗口大小?也許在窗口的樣式掩碼中添加NSResizableWindowMask可以解決問題嗎?你應該試一試。

  2. Another suggestion - check that the content of your window resizes correctly along with the window. You set your window to transparent. But if there is no content inside the window, no shadow is displayed. You can also try to add your view as a subview to the existing window's contentView instead of replacing it.

    另一個建議 - 檢查窗口內容是否與窗口一起正確調整大小。您將窗口設置為透明。但如果窗口內沒有內容,則不顯示陰影。您還可以嘗試將視圖作為子視圖添加到現有窗口的contentView,而不是替換它。

I have almost the same setup in my project and I can tell that window's shadow is displayed correctly when you resize the window.

我在項目中的設置幾乎相同,我可以告訴您在調整窗口大小時正確顯示窗口的陰影。

P.S. A recommendation: do not rely on 'self' in the initialization method of the object. It may be yet not fully ready for use. Init with minimum, adjust the window after it was creater in your controller (for example, you cannot be sure that setFrame:display will do what you expect with correct sizes). The glitch you have might be related to this also.

附:建議:不要在對象的初始化方法中依賴'self'。它可能尚未完全准備好使用。初始化為最小值,在控制器中創建窗口之后調整窗口(例如,您無法確定setFrame:display會按照您所期望的正確尺寸執行操作)。你所遇到的故障也可能與此有關。

#2


2  

Maybe it's better to switch off shadow at the beginning of the animation and back on when you are done. Do not switch this setting during animation. I thought I have seen this also with other windows.

也許最好在動畫開始時關閉陰影,並在完成后重新開啟。動畫期間請勿切換此設置。我以為我也和其他窗戶見過這個。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2013/04/22/721206dee16b7cadc7140541de00c6d1.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com