我尝试使用可变宽度字体创建两列左对齐文本。我目前的流程:
这对我来说听起来很合理,但输出看起来像这样(使用可变宽度字体):
a 12345678910
as 12345678910
asd 12345678910
asdf 12345678910
asdfg 12345678910
我正在寻找的输出是:
a 12345678910
as 12345678910
asd 12345678910
asdf 12345678910
asdfg 12345678910
我错过了什么?
const int maxNameWidth = 150;
Font measurementFont;
Graphics graphics;
float spaceWidth;
void Main()
{
measurementFont = new Font("Arial", 14);
graphics = Graphics.FromImage(new Bitmap(1, 1));
spaceWidth = graphics.MeasureString(" ", measurementFont).Width;
addRow("a", "12345678910");
addRow("as", "12345678910");
addRow("asd", "12345678910");
addRow("asdf", "12345678910");
addRow("asdfg", "12345678910");
measurementFont.Dispose();
graphics.Dispose();
}
void addRow(string name, string value) {
float width = graphics.MeasureString(name, measurementFont).Width;
int amountOfSpacesNeeded = Convert.ToInt32((maxNameWidth - width) / spaceWidth);
Console.WriteLine(name + " ".PadRight(amountOfSpacesNeeded) + content); // The console font is Arial
}
编辑:修正了填充name
的哑误差,而不是实际乘以空格量。结果现在好多了,但还是有点偏。我注意到五个空格的宽度不等于spaceWidth * 5
但是......
答案 0 :(得分:2)
终于明白了。但是我认为这个解决方案令人厌恶垃圾,所以我会保持这个问题的开放,直到某人有一个更好/更少暴力的方法。
基本上,由于无法计算的字距调整计算得到了1-2个空格(据我可以谷歌),我只是再次测量字符串并在其中添加或减去空格,直到它到达{{的另一侧1}}从它的方向;例如。如果它太短,那么再添加一个空格,再次测量并查看是否超过maxNameWidth
,如果是,则停止,反之亦然。
完整代码:
maxNameWidth
输出(用14pt Arial粘贴某处以查看对齐方式):
const int maxNameWidth = 150;
Font measurementFont;
Graphics graphics;
float spaceWidth, xWidth;
enum Direction { None, FromHigh, FromLow };
void Main()
{
measurementFont = new Font("Arial", 14);
graphics = Graphics.FromImage(new Bitmap(1, 1));
spaceWidth = graphics.MeasureString(" ", measurementFont).Width;
xWidth = graphics.MeasureString("x", measurementFont).Width;
addRow("a", "12345678910");
addRow("as", "12345678910");
addRow("asd", "12345678910");
addRow("asdf", "12345678910");
addRow("asdfg", "12345678910");
measurementFont.Dispose();
graphics.Dispose();
}
void addRow(string name, string value) {
float width = graphics.MeasureString(name, measurementFont).Width;
int amountOfSpacesNeeded = Convert.ToInt32((maxNameWidth - width) / spaceWidth);
string firstColumn = name + " ".PadRight(amountOfSpacesNeeded);
float currWidth;
Direction dir = Direction.None;
while (true) {
// I add an 'x' here because just measuring a bunch of spaces does not work (the width of one space is apparently equal to the width of five according to graphics)
currWidth = graphics.MeasureString(firstColumn + "x", measurementFont).Width - xWidth;
if (((dir == Direction.FromLow) || (dir == Direction.None)) && (currWidth < maxNameWidth)) {
dir = Direction.FromLow;
firstColumn += " ";
}
else if (((dir == Direction.FromHigh) || (dir == Direction.None)) && (currWidth > maxNameWidth)) {
dir = Direction.FromHigh;
firstColumn = firstColumn.Remove(firstColumn.Length - 1);
}
else {
break;
}
}
Console.WriteLine(firstColumn + value);
}
答案 1 :(得分:1)
在我编写此代码时,作者已添加了自己的解决方案。然而,虽然他的代码似乎可以完成它的工作,但却增加了解决方案的复杂性。我的代码有一个更简单的算法。
void addRows(string name, string value)
{
string teststring = name + "";
int spacesAdded = 0;
while (maxNameWidth > graphics.MeasureString(teststring + "x", measurementFont).Width)
{
spacesAdded++;
teststring += " ";
}
Console.WriteLine(":" + name + " ".PadRight(spacesAdded) + ":" + value + ":" + spacesAdded);
}
我使用“x”获得与他相似的结果,它可以被其他字符替换,以测试更多的字符串,看它是否有效。我测试了只有2个额外的字符串,其中包括非常宽的“ooooo”和非常窄的“.....”以获得令人满意的结果。
PS:看来我以前在回答时的想法与众不同。由于我也在尝试学习新事物并寻找新方法,因此我试图得到这个问题的结果。无论如何,这次我走在正确的道路上