当图像插入一行时,NSTextField 在 NSTableView 中变得模糊
NSTextField is blurry in NSTableView when image is inserted in a row
在我基于视图的 NSTableView 中,每个视图都有一个 NSTextField 和一个位于文本字段正下方的 NSImageView。
有时,当我在 table 的顶部插入一个新行时,该行的 NSImageView 中有一个图像, 其他行中的文本 变为 blurry/degraded.
滚动几次后文字又正常了
不行:
好的:
文本仅在行之后带有图像的行模糊的示例:
这真的让我觉得这是来自 .insertRows
或 noteHeightOfRows
的问题。
所有元素都在 IB 中设置了自动布局约束。
滚动视图在IB中设置了CoreAnimation层。我在准备单元格时也使用了层:
cell.layer?.isOpaque = true
cell.textLabel.layer?.isOpaque = true
有时
cell.layer?.borderColor = someColor
cell.layer?.borderWidth = someWidth
行插入:
// update the model, then:
NSAnimationContext.runAnimationGroup({ (context) in
context.allowsImplicitAnimation = true
self.table.insertRows(at: index, withAnimation: [.effectGap])
})
正在用图像更新行:
// in tableViewCell, while populating the table
cell.postImage.image = img
cell.postImage.needsDisplay = true
// once the image is downloaded
table.reloadData(forRowIndexes: ..., columnIndexes: ...)
table.noteHeightOfRows(withIndexesChanged: ...)
如何避免这个问题?很难调试,因为它并不总是发生,而且我看不出它发生时发生的原因。
由于文本只有在插入图像时才会变得模糊,我的第一个想法是 NSTextField 的框架不是 "integral"(它的像素值不是整数)。这是导致文本模糊的众所周知的原因。
您正在使用 Cocoa 的自动布局功能,所以我的建议是覆盖基于视图的 table 视图单元格中的 void layout()
方法。
调用它的 super 方法(让 Cocoa 进行所有需要的布局计算)并且只是将 textFiled 的框架设置为相同的框架,但不可分割。
附录:虽然 textField 本身可能有一个完整的框架 - 它仍然可以布置在 "half pixel"(在实际屏幕坐标中)上,这仍然会导致模糊。
TextField 是单元格的子视图,因此它的框架不在屏幕坐标中,而是在单元格坐标中。
示例:假设单元格有一个 (0.5, 0.5 , 100, 100)
的框架,它不是完整的,而 textField 有一个 (10,10, 50, 50)
的完整框架,它无论如何都是完整的!
但是当 textField 将在屏幕上布局时,它将具有以下框架:(10.5, 10.5, 50, 50)
这不是完整的 - 并且会导致在 "half pixel" 上绘制 textField(不是完整的) 导致文本模糊。
因此,在您的情况下,单元格本身必须与文本字段一起布置在一个整体框架上,以确保文本字段在屏幕坐标中位于整体框架上。
在您的 tableViewCell 子类中:
void layout()
{
[super layout];
//**** We have to ensure that the cell is also layed on an integral frame ****//
[self setFrame:NSIntegralRect(self.frame)];
//At this point after calling the [super layout]; myTextField will have a valid (autolayoutwise) frame so all you have to do is to ensure that it is indeed an integral frame doing so by calling NSIntegralRect(NSRect rect); method of Cocoa framework.
[myTetxField setFrame:NSIntegralRect(myTextField.frame)];
//Maybe optionally you will want to set everything to the integral rect :-)
/*
for(NSView * view in self.subViews)
{
[view setFrame:NSIntegralRect(view.frame)];
}
*/
}
在我基于视图的 NSTableView 中,每个视图都有一个 NSTextField 和一个位于文本字段正下方的 NSImageView。
有时,当我在 table 的顶部插入一个新行时,该行的 NSImageView 中有一个图像, 其他行中的文本 变为 blurry/degraded.
滚动几次后文字又正常了
不行:
好的:
文本仅在行之后带有图像的行模糊的示例:
这真的让我觉得这是来自 .insertRows
或 noteHeightOfRows
的问题。
所有元素都在 IB 中设置了自动布局约束。
滚动视图在IB中设置了CoreAnimation层。我在准备单元格时也使用了层:
cell.layer?.isOpaque = true
cell.textLabel.layer?.isOpaque = true
有时
cell.layer?.borderColor = someColor
cell.layer?.borderWidth = someWidth
行插入:
// update the model, then:
NSAnimationContext.runAnimationGroup({ (context) in
context.allowsImplicitAnimation = true
self.table.insertRows(at: index, withAnimation: [.effectGap])
})
正在用图像更新行:
// in tableViewCell, while populating the table
cell.postImage.image = img
cell.postImage.needsDisplay = true
// once the image is downloaded
table.reloadData(forRowIndexes: ..., columnIndexes: ...)
table.noteHeightOfRows(withIndexesChanged: ...)
如何避免这个问题?很难调试,因为它并不总是发生,而且我看不出它发生时发生的原因。
由于文本只有在插入图像时才会变得模糊,我的第一个想法是 NSTextField 的框架不是 "integral"(它的像素值不是整数)。这是导致文本模糊的众所周知的原因。
您正在使用 Cocoa 的自动布局功能,所以我的建议是覆盖基于视图的 table 视图单元格中的 void layout()
方法。
调用它的 super 方法(让 Cocoa 进行所有需要的布局计算)并且只是将 textFiled 的框架设置为相同的框架,但不可分割。
附录:虽然 textField 本身可能有一个完整的框架 - 它仍然可以布置在 "half pixel"(在实际屏幕坐标中)上,这仍然会导致模糊。
TextField 是单元格的子视图,因此它的框架不在屏幕坐标中,而是在单元格坐标中。
示例:假设单元格有一个 (0.5, 0.5 , 100, 100)
的框架,它不是完整的,而 textField 有一个 (10,10, 50, 50)
的完整框架,它无论如何都是完整的!
但是当 textField 将在屏幕上布局时,它将具有以下框架:(10.5, 10.5, 50, 50)
这不是完整的 - 并且会导致在 "half pixel" 上绘制 textField(不是完整的) 导致文本模糊。
因此,在您的情况下,单元格本身必须与文本字段一起布置在一个整体框架上,以确保文本字段在屏幕坐标中位于整体框架上。
在您的 tableViewCell 子类中:
void layout()
{
[super layout];
//**** We have to ensure that the cell is also layed on an integral frame ****//
[self setFrame:NSIntegralRect(self.frame)];
//At this point after calling the [super layout]; myTextField will have a valid (autolayoutwise) frame so all you have to do is to ensure that it is indeed an integral frame doing so by calling NSIntegralRect(NSRect rect); method of Cocoa framework.
[myTetxField setFrame:NSIntegralRect(myTextField.frame)];
//Maybe optionally you will want to set everything to the integral rect :-)
/*
for(NSView * view in self.subViews)
{
[view setFrame:NSIntegralRect(view.frame)];
}
*/
}