当表滚动时,为什么NSTextField会在NSTableView上留下工件?

时间:2014-03-04 12:02:38

标签: macos cocoa nstableview nstextfield

我想在滚动表上放置一个文本标签,但标签与滚动图形冲突。在这里你可以看到一个测试,我有意将标签的一半放在桌子外面并在表格中向上滚动,这导致标签覆盖的一部分被拖动,直到它退出窗口

scrolling up breaks label overlay

此外,当我走到桌子的另一端并向下滚动时,有时标签似乎被重新绘制,并且它的大块随着滚动一起上升:

scrolling down is bad too

scrolling down is bad too

表似乎正在重绘其内容,并且在它们被覆盖时不会通知其余的视图对象重绘自己。我该如何解决这个问题?事实上,这似乎与How to place an NSButton over an NSTableView高度相关,它似乎有相同的问题,但有一个按钮而不是标签。

4 个答案:

答案 0 :(得分:1)

不要这样做,因为你会失去很多表现并增加能量消耗。

尝试使用NSScrollView方法 - (void)addFloatingSubview:(NSView *)view forAxis:(NSEventGestureAxis)axis

答案 1 :(得分:1)

这是因为滚动视图设置为在滚动时复制其内容,并仅重新绘制新发现的部分作为性能优化。要关闭它,请使用

myScrollView.contentView.copiesOnScroll = NO;

虽然这会让滚动使用更多CPU(你也可以在XIB中执行此操作,查找'滚动副本'复选框)。

可能更好的方法是将滚动视图和按钮切换为图层支持:

myTableView.enclosingScrollView.wantsLayer = YES;
myTextView.wantsLayer = YES;

(同样,您可以在XIB文件的“图层”检查器中设置此项,您可以在其中单击每个视图旁边的复选框以为其指定图层)现在,滚动视图将仅复制其自身图层中的内容(不再包含您的文本视图)。此外,现在所有文本视图的合成都将在图形卡中完成。但是,如果将文本放在其自己的图层中的透明背景上,则会丢失子像素消除锯齿。但如果它是任何其他类型的视图(或者你的文本后面实际上有一个坚实的背景),那么看起来会很好。

答案 2 :(得分:1)

另一种获得正确重绘的替代方法是在Effects Inspector中打开xib根视图,并将其标记为使用Core Animation Layer。这避免了需要使用重绘钩子创建自定义类。

答案 3 :(得分:0)

是的,似乎NSTableView 缓存孔表的绘图,以便滚动视图不必为每个像素刷新它。然而,这正是所需要的。幸运的是,它可以完成,我设法通过以下方式子类化NSScrollView以向reflectScrolledClipView:添加属性和挂钩:

@interface EHScrollView : NSScrollView

@property (nonatomic, weak) NSView *refreshView;

@end

实施将是:

#import "EHScrollView.h"

@implementation EHScrollView

- (void)reflectScrolledClipView:(NSClipView *)aClipView
{
    [super reflectScrolledClipView:aClipView];
    [self.refreshView setNeedsDisplay:YES];
}

@end

然后,唯一需要修改用户界面的xib。如果表嵌入在滚动视图中,请选择滚动视图并对其进行修改以继承自定义类EHScrollView。然后,在视图控制器初始化中,使用出口滚动视图和表视图,通过refreshView属性将后者链接到前者。

现在,每个滚动都会自动调用setNeedsDisplay:上的refreshView,这意味着表格和覆盖在顶部的任何内容都将重新绘制。当然,这比非刷新表更具性能,所以只在有意义的地方使用。