【问题标题】:Unit of measurement of Method: String.LengthMethod的计量单位:String.Length
【发布时间】:2016-12-14 21:48:54
【问题描述】:

我正在尝试根据其内容宽度设置标签(“label1”)的宽度。但是每次我用String.Length-Method获取字符串的长度时,宽度似乎太小了,我的字符串不适合标签。

  string anystring = "ThisIsMyString";
  int i = anystring.Length;
  label1.Text = anystring;
  label1.Width = i + 10; //I add +10 to have some buffer

String.Length 和 Label.Width 有不同的度量单位的问题吗?有没有其他方法可以处理这个问题? (我知道我可以简单地将设置标签宽度的部分省略,但出于好奇,我想知道如何做到这一点)

【问题讨论】:

  • 字符串的长度是字符数,其中控件的宽度是它的像素大小(默认情况下)。但是,您可以将字符数乘以恒定的像素数。
  • string.Length 只是字符数......它与宽度无关 - 要了解某些 UI 元素的宽度,您需要很多上下文 - 包括字体、字体大小等。你可能想要Graphics.MeasureString?
  • Label.AutoSize 属性设置为true
  • 我明白你的意思。我会尝试 Graphics.MeasureString 和 Label.AutoSize 谢谢
  • @AlexanderPetrov 与 AutoSize 属性它工作正常。但是我想通过在代码中自己设置标签的宽度来解决这个问题。

标签: c# winforms visual-studio


【解决方案1】:

当使用 Windows 显示在屏幕上时,确定文本 widthsize 的正确方法是使用 Graphics.MeasureString:

使用指定字体绘制时测量指定字符串。

这样做的原因是以下因素会影响您返回的确切大小:

  • 显然是文字
  • 使用的字体系列/类型
  • 使用的字体大小
  • 字体样式(粗体、斜体等)

这是一个非常简短的例子:

using (var f = new Font("Arial", 8.25f))
using (var g = Graphics.FromHwnd(IntPtr.Zero)) // Desktop
{
    SizeF size = g.MeasureString("Test", f);
}

显然您应该使用从控件获得的Graphics 对象和标签的字体(如果您打算将其用作标签)以避免构造和使用上述对象。

【讨论】:

  • 哈!好吧,看看我重新发明轮子。永远都不会猜到 .NET 有一些原生的东西可以做到这一点。
  • 现在我正在尝试这样做。但我不确定该怎么做。 Microsoft 方面的示例生成一个事件。我真的不知道如何调用这个事件,我需要它。所以这是我的活动:private void MeasureStringMin(string str, Font stringFont , Label lbl, PaintEventArgs e)
  • @MaChaToc 您需要在Label 上附加Paint 事件的事件处理程序。因此,如果您转到应用程序的设计视图,单击Label 控件,然后转到属性表上的事件选项卡,将出现Paint 条目。双击那里,它会自动连接Paint 事件。然后您基本上可以使用@LasseV.Karlsen 链接中示例中的代码。
  • @sab669 这就是我所缺少的
  • @LasseV.Karlsen 成功了,谢谢!除了您的代码之外,我只需将 autosize 属性设置为 false 并将 size.Width 转换为 Int32。对于任何可能对我在using (var g ...) 中的代码感兴趣的人,最终看起来像这样:label1.AutoSize = false; SizeF size = g.MeasureString(button1.Text, f); int i = Convert.ToInt32(size.Width); label1.Width = i; label1.Text = Convert.ToString(i);
【解决方案2】:

嗯,对你的问题的简短回答:

是String.Length和Label.Width的度量单位不同的问题吗?

是“是”。

有关Width 属性的更多信息,请参阅here,有关String.Length 的更多信息,请参阅here

基本上:String.Length 指的是字符串中的字符数。 “ABC123”将返回 6。Control.Width 是以像素为单位的测量值。而且由于不同的字体看起来不同,因此尝试找出“X 字体中的 N 个字符是 Y 像素”将是非常麻烦。 (编辑:假设您使用的是单宽字体。如果不是,它甚至更复杂,因为“iii”明显比“aaa”长。)

关于您的后续行动:

还有其他方法可以解决这个问题吗?

(编辑:在 cmets 中提出想法后更改此部分)

1) 将字符串写入图像文件

2) 找到一个合适的库,可以根据图像中的一个坐标或一组坐标确定颜色

3) 在图像的像素行上循环 N 次,其中 N = 图像的高度

4) 寻找包含黑色像素的线条。我们不想要全白的行,因为那只是我们文本上方和下方的“缓冲区”。

5) 遍历当前行中的每个像素并存储第一个黑色像素的X 坐标,然后将第一个黑色像素之后的每个黑色像素的X 坐标存储在“临时”变量中

6) 将lastBlackPixelfirstBlackPixel 之间的差异存储在一个变量中

7) 比较图像中每一行的这两个点之间的差异。如果当前差值大于largestKnownDifference,则使用新距离更新该变量。

这应该确定文本的宽度。或者也许迭代每一列并存储第一个黑色像素的位置,然后存储最后一列的位置以包含一个黑色像素?我不知道,我还没有喝咖啡。给猫剥皮的方法很多。

【讨论】:

  • 您甚至不能说“字体 X 中有 N 个字符”,因为根据 哪些 个字符,宽度也可能会有所不同。 EG 在大多数字体中,W 比 I 宽很多
  • 真的,真的。它因字体、大小、用户的个人显示设置而异——各种各样。
  • @sab669 我是直接在代码中赋值的,不打算在程序运行过程中更改。这只是一些简单的练习,我试图更好地理解这些方法。
  • @MaChaToc Got'chya。我确定那里有一个库可以将文本写入图像文件,然后正如我所说,使用另一个库来确定文本的最左边和最右边不是背景颜色的像素(大概是白色) 然后使用这些点来确定宽度。这可能是确定这类事情的最可靠的方法,但仍然相当困难。不过,这可能是一个很好/有趣的学习练习!
  • @sab669 你说的很有趣。但是最左边和最右边的像素是什么意思?
【解决方案3】:

您可以查看Label 的autosize property。将此设置为 true 将使标签根据字符串大小调整其宽度。但是,对于很长的文本,这可能无法获得预期的结果。

如果你希望能够放长文本而不是获得很长的标签,你可以通过设置它的MaximumSize来换行。

[编辑] 我认为可以通过设置自动调整后的宽度(后验)来进行测量。

另一种方法是尝试使用Graphics.MeasureString 来测量文本,该Graphics.MeasureString 使用实际文本并使用字体来提供大小。可以在here (apriori) 找到一个完整的工作示例。

【讨论】:

  • 鉴于 OP 状态 (I know that I could simply leave the part out where I set the label's width, but I'd like to know how to do it that way out of curiosity),我认为他知道 如何 将文本放入标签并使其适合。他们只想知道如何以编程方式确定给定字符串的宽度。如果标签是以编程方式创建的,EDIT 没有意识到 AutoSize 默认为 false。所以这实际上非常好知道!我以为它总是默认为true
猜你喜欢
  • 2017-08-03
  • 1970-01-01
  • 2017-12-11
  • 2016-06-11
  • 2019-06-10
  • 1970-01-01
  • 2016-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多