Why does an NSTextField leave artifacts over an NSTableView when the table scrolls?

自作多情 提交于 2020-01-24 16:08:29

问题


I want to put a text label over a scroll table but the label conflicts with the drawing of the scrolling. Here you can see a test where I've intentionally put the label half out of the table and scroll up in the table, which results in the part of the label overlay being dragged below until it exits the window.

Also, when I go to the other end of the table and scroll down, sometimes the label seems to be redrawn and chunks of it go up along with the scroll:

It seems that the table is redrawing its contents and does not notify the rest of the view objects to redraw themselves in case they are overlaid. How do I solve this? In fact, this seems highly related to How to place an NSButton over an NSTableView which seems to have the same problem but with a button instead of a label.


回答1:


Dont do that because you will lose a lot of performance and increase energy use.

Try the NSScrollView method - (void)addFloatingSubview:(NSView *)view forAxis:(NSEventGestureAxis)axis




回答2:


That's because the scroll view is set to copy its contents when scrolling and only redraw the newly-uncovered part as a performance optimization. To turn that off, use

myScrollView.contentView.copiesOnScroll = NO;

though that will make scrolling use more CPU (you can also do this in the XIB, look for a 'copies on scroll' checkbox).

Probably a better approach would be to switch the scroll view and the button to be layer-backed:

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

(Again, you can set this in the 'Layers' inspector of the XIB file, where you can click a checkbox next to each view to give it a layer) Now, the scroll view will only copy stuff from its own layer (which no longer includes your text view). Also, now all the compositing of the text view will be done using in the graphics card. However, if you put text on a transparent background in its own layer, you lose sub-pixel anti-aliasing. But if it's any other kind of view (or there's actually a solid background behind your text) this will look fine.




回答3:


Another alternative way to get proper redrawing is to open the xib root view in the Effects Inspector, and mark it to use the Core Animation Layer. This avoids requiring to create a custom class with the redrawing hook.




回答4:


Yes, it seems that NSTableView caches the drawing of the hole table so that the scroll view doesn't have to refresh it for every pixel. However, that's exactly what is needed. Fortunately it can be done, I managed to subclass the NSScrollView in the following way to add a property and a hook to reflectScrolledClipView::

@interface EHScrollView : NSScrollView

@property (nonatomic, weak) NSView *refreshView;

@end

The implementation would be:

#import "EHScrollView.h"

@implementation EHScrollView

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

@end

The only thing needed then is to modify the xib for the user interface. Where the table is embedded in a scroll view, select the scroll view and modify it to inherit the custom class EHScrollView. Then, in the view controller initialisation, use outlets to both the scroll view and the table view to link the latter to the former through the refreshView property.

Now, every single scroll will automatically call setNeedsDisplay: on refreshView, which means that both the table and whatever is overlaid on top will be redrawn. Of course this is more performance intensive than a non refreshing table, so use only where it makes sense.



来源:https://stackoverflow.com/questions/22171410/why-does-an-nstextfield-leave-artifacts-over-an-nstableview-when-the-table-scrol

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!