如何设置文本单元格中的字体大小,以便字符串填充单元格的矩形?
我有一个包含两个 NSTextFieldCell
的视图。绘制这些单元格的大小是根据视图的大小得出的,我希望每个单元格中的文本是最大的,适合单元格的导出大小。这是我所拥有的,它没有设置字体大小:
- (void)drawRect:(NSRect)dirtyRect {
/*
* Observant readers will notice that I update the whole view here. If
* there is a perceived performance problem, then I'll switch to just
* updating the dirty rect.
*/
NSRect boundsRect = self.bounds;
const CGFloat monthHeight = 0.25 * boundsRect.size.height;
NSRect monthRect = NSMakeRect(boundsRect.origin.x,
boundsRect.origin.y + boundsRect.size.height
- monthHeight,
boundsRect.size.width,
monthHeight);
[monthCell drawWithFrame: monthRect inView: self];
NSRect dayRect = NSMakeRect(boundsRect.origin.x,
boundsRect.origin.y,
boundsRect.size.width,
boundsRect.size.height - monthHeight);
[dayCell drawWithFrame: dayRect inView: self];
[[NSColor blackColor] set];
[NSBezierPath strokeRect: boundsRect];
}
所以我知道我可以询问一个字符串对于给定的属性需要什么大小,并且我知道我可以要求一个控件更改其大小以适应其内容。这些似乎都不适用:我希望内容(在本例中为单元格的 stringValue
)的大小适合已知的矩形尺寸,而实现该目的所需的属性未知。我怎样才能找到需要的尺寸?假设我知道我将使用什么字体(因为我知道)。
更新注意:我不想截断字符串,我想增长或收缩它,以便整个内容以尽可能最大的文本大小适合提供的矩形。
I have a view that contains two NSTextFieldCell
s. The size at which these cells are drawn is derived from the size of the view, and I want the text in each cell to be the largest that will fit in the derived size of the cell. Here's what I have, which doesn't set the font size:
- (void)drawRect:(NSRect)dirtyRect {
/*
* Observant readers will notice that I update the whole view here. If
* there is a perceived performance problem, then I'll switch to just
* updating the dirty rect.
*/
NSRect boundsRect = self.bounds;
const CGFloat monthHeight = 0.25 * boundsRect.size.height;
NSRect monthRect = NSMakeRect(boundsRect.origin.x,
boundsRect.origin.y + boundsRect.size.height
- monthHeight,
boundsRect.size.width,
monthHeight);
[monthCell drawWithFrame: monthRect inView: self];
NSRect dayRect = NSMakeRect(boundsRect.origin.x,
boundsRect.origin.y,
boundsRect.size.width,
boundsRect.size.height - monthHeight);
[dayCell drawWithFrame: dayRect inView: self];
[[NSColor blackColor] set];
[NSBezierPath strokeRect: boundsRect];
}
So I know that I can ask a string what size it would take for given attributes, and I know that I can ask a control to change its size to fit its content. Neither of those seems applicable: I want the content (in this case, the cell's stringValue
) to size to fit the known rect dimensions, with the attributes needed to achieve that being unknown. How can I find the needed size? Assume that I know what font I'll be using (because I do).
update Note: I don't want to truncate the string, I want to grow or shrink it so that the whole thing fits, with the largest text size possible, into the provided rect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我使用一些类似的代码,但它可以处理不同的字体,最大尺寸为 10,000,并考虑可用的高度以及文本显示区域的宽度。
I use some similar code but it handles different fonts, sizes up to 10,000 and takes into account the available height as well as width of the area the text is being displayed in.
建议我在带外尝试二分搜索以获得合适的大小。这是一个非常有限的例子:
限制(你最好不需要 32pt 或更大的字体,或者任何不是 Lucida Grande 的字体)对于我的需求来说并不重要,但肯定会让一些人放弃使用这种方法。我将保留这个问题,并接受更稳健的方法。
It was recommended out of band that I try a binary search for an appropriate size. This is a very limited example of that:
The limitations (you'd better not need a 32pt or larger font, or anything that ain't Lucida Grande) are not important for my need, but certainly would put some people off using this method. I'll leave the question open, and accept a more robust approach.
这是一种不进行猜测和检查的方法。根据字体的不同,可能需要一点填充来防止溢出(sizeWithAttributes 不能完美缩放)。繁荣!
Here is a method that does not do guess and check. Depending on the font, a little padding may be necessary to prevent overflow (sizeWithAttributes doesn't scale perfectly). Boom!
两个想法。我尝试过一个,另一个可能有效:
1)像这个问题一样: 如何根据图形宽度截断 NSString? 即尝试不同的大小,直到它不再适合
2)创建单元格,给它最大的矩形并将其设置为将其文本放入单元格中,然后询问其理想大小(那里有一个方法可以做到这一点),然后再次调整单元格大小。最后,如果我正确理解了你的问题。
Two ideas. One I've tried, the other might work:
1) Do like in this question: How to truncate an NSString based on the graphical width? i.e. just try out different sizes until it doesn't fit anymore
2) Create the cell, give it the maximum rect and set it to fit its text into the cell, then ask it for its ideal size (there's a method on there that does that) then resize the cells again. At last if I understood your problem correctly.
就我而言,我使用以下内容:
In my case I use the following:
抱歉:五年过去了。文本宽度可能不再是您清醒生活中最关心的问题。不过,我已经有了答案;也许其他人会受益。
准确调整文本宽度大小(这也适用于文本高度)的关键是要认识到渲染文本的宽度当然会变化 - 但呈线性变化! - 通过 font-size 属性的设置。当具有线性函数时,无需进行二分搜索或挑选并测试所有可能的字体大小属性值;只需确定图表上的两点即可。
准备时,不要绘制字符串,而是计算渲染字符串的宽度,例如,文本大小为 20 和文本大小为 40。这将为您提供线性函数“渲染字符串宽度作为以下函数的函数”的两个数据点文本大小属性”。然后,推断以使字符串适合您当前需要的任何渲染宽度。
我发现这种方法可以均匀地产生良好且快速的结果。当然,随着字体的变化,有时您可能会获得在边界框边缘上方悬挂两个或三个像素的字符 - 但这是字体设计的产物。精心设计的字体效果会很好,即使是疯狂的字体,通常也只需要提供几个像素的边框余地。
以下是我上个月遇到此问题时使用的例程。请随意使用此代码。
Sorry: it's been five years. Text width might no longer be the paramount concern in your waking life. However, I have the answer; maybe others will benefit.
The crucial key to accurate text-width-sizing (and this works also for text-height) is to realize that the width of rendered text does of course vary - but linearly! - with the setting of the font-size attribute. There is no need to binary search, or to pick through and test all the possible font-size attribute values, when one has a linear function; one only needs to be sure of two points on the graph.
To prepare, don't draw the string, but calculate the width of your rendered string at, for example, text size 20 and at text size 40. This gives you two data points on the linear function "rendered string width as a function of text-size attribute". Then, extrapolate to fit the string into whatever rendered width you currently need.
I have found this method to uniformly yield good and fast results. With variations in font, of course, sometimes you might obtain characters that hang two or three pixels over the edge of the bounding box - but this is an artefact of font design. The well-designed fonts will work well, and even with crazy fonts, one usually has to only provide a few pixels' border of leeway.
Here are the routines I used when I had this problem last month. Feel free to use this code.