我需要在不同的字体和字体大小上获得最大宽度1,2,3,.... 8,9。
在c#中,开源代码是:
protected double MaxDigitWidth(string fontName, double dblSizePt)
{
double dblMaxDigitWidth = 0.0;
// Excel does not use the specified font size,
// instead, font size is rounded to an integral pixel size
// check if this works on non-Windows platforms, otherwise 96dpi could do fine here
// Graphics g = System.Drawing.Graphics.FromHwnd(new IntPtr());
float fSizePxl = (float)Math.Round(96 * dblSizePt / 72);
float fSizePt = (72 * fSizePxl / 96);
FontStyle fontStyle;
if (fontName == "Monotype Corsiva")
fontStyle = FontStyle.Italic;
else
fontStyle = FontStyle.Regular;
Font font = new Font(fontName, fSizePt, fontStyle, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
for (int i = 0; i < 10; i++)
{
// use a Label on a .NET 2.0 Form to measure the width of a digit
Form f = new Form();
Label l = new Label();
l.UseCompatibleTextRendering = false;
l.Font = font;
l.AutoSize = true;
f.Controls.Add(l);
l.Text = Convert.ToString(i) + Convert.ToString(i);
f.ResumeLayout(false);
f.PerformLayout();
int iWidth2 = l.Width;
l.Text = Convert.ToString(i);
f.PerformLayout();
// we measure twice so we can remove the padding
int iWidth1 = l.Width;
if (iWidth2 - iWidth1 > dblMaxDigitWidth)
{
dblMaxDigitWidth = iWidth2 - iWidth1;
}
}
return dblMaxDigitWidth;
}
我用Java实现了它。但结果却不同。
protected double MaxDigitWidth(String fontName, double dblSizePt)
{
double dblMaxDigitWidth = 0.0;
Font f;
if (fontName == "Monotype Corsiva")
f = new Font(fontName, Font.ITALIC ,(int)dblSizePt);
else
f = new Font(fontName, Font.PLAIN ,(int)dblSizePt);
JComponent t = new JLabel();
FontMetrics fm = t.getFontMetrics(f);
for (int i = 0; i < 10; i++)
{
int iWidth2 = fm.stringWidth(String.valueOf(i)+String.valueOf(i));
int iWidth1 = fm.stringWidth(String.valueOf(i));
if (iWidth2 - iWidth1 > dblMaxDigitWidth)
{
dblMaxDigitWidth = iWidth2 - iWidth1;
}
}
return dblMaxDigitWidth;
}
但结果在c#和java之间是不同的。(我在同一台机器上运行它们。)
c#
的结果 Font and Font size Maximum digit widht
a = MaxDigitWidth("Arial", 11.0); 8
a = MaxDigitWidth("Arial", 12.0); 9
a = MaxDigitWidth("Arial", 13.0); 9
a = MaxDigitWidth("Arial", 14.0); 11
a = MaxDigitWidth("Arial", 15.0); 11
a = MaxDigitWidth("Arial", 16.0); 12
a = MaxDigitWidth("Arial", 17.0); 13
a = MaxDigitWidth("Arial", 18.0); 13
a = MaxDigitWidth("Arial", 19.0); 14
a = MaxDigitWidth("Arial", 20.0); 15
java的结果
Arial-11 6.0
Arial-12 7.0
Arial-13 7.0
Arial-14 8.0
Arial-15 8.0
Arial-16 9.0
Arial-17 9.0
Arial-18 10.0
Arial-19 11.0
Arial-20 11.0
答案 0 :(得分:3)
.NET和Java之间的区别是由于对屏幕分辨率的不同假设。 .NET适用于96dpi,Java适用于72dpi。也就是说,如果你向Java询问12pt字体,它在屏幕上的大小将与你要求.NET使用相同字体的大小不同。在纸面上,它们将是相同的。
如果将结果转换为mm(或英寸),除了由于四舍五入而导致的精度损失之外,您会发现它们是相同的。
我还通过从Microsoft Word打印一些数字并测量它们来验证数字。这种现实检查通常会有所帮助。
你测量.NET中的文本长度非常有趣。为什么不这样做:
using System;
using System.Drawing;
namespace Codo
{
class Program
{
static void Main(string[] args)
{
Bitmap bitmap = new Bitmap(100, 100);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.PageUnit = GraphicsUnit.Pixel;
StringFormat strFormat = new StringFormat(StringFormat.GenericTypographic);
for (int fontSize = 11; fontSize <= 20; fontSize++)
{
Font font = new Font("Arial", fontSize, FontStyle.Regular);
float digitWidth = graphics.MeasureString("00000000", font, 1000, strFormat).Width / 8;
font.Dispose();
Console.WriteLine("Width of digit 0 for {0} {1}pt: {2} (96dpi)", font.FontFamily.Name, font.SizeInPoints, digitWidth);
digitWidth = digitWidth / 96 * 72;
Console.WriteLine("Width of digit 0 for {0} {1}pt: {2} (72dpi)", font.FontFamily.Name, font.SizeInPoints, digitWidth);
}
graphics.Dispose();
bitmap.Dispose();
}
}
}
答案 1 :(得分:1)
嗯,我说问题是你正在使用不同的方法。在Java中,您只需使用甚至不显示/布局的标签的FontMetrics
,而在C#中,您似乎正在使用可能已调整大小并包含填充,边框等标签的大小。
此外,在您的Java代码中,您将dblSizePt
截断为整数,丢失任何可能的小数部分。在C#中,您直接通过fSizePt
Font
construtctor。
最后但并非最不重要的是,您使用的两个不同的UI框架在文本呈现方面可能略有不同。