首页 > 解决方案 > 如何垂直对齐非等宽文本

问题描述

我正在尝试使用可变宽度字体创建两列左对齐的文本。我目前的流程:

  1. 测量将进入第一列的字符串
  2. 从所述第一列的最大宽度中减去其宽度以获得差值
  3. 将其除以单个空格的宽度以获得所需的空格数
  4. 用必要数量的空格右填充结果

这在我看来合乎逻辑,但输出看起来像这样(使用可变宽度字体):

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...

标签: c#.net

解决方案


终于明白了。但是我认为这个解决方案是令人作呕的垃圾,所以我会一直打开这个问题,直到有人有更好/更少的蛮力方法。

基本上,由于无法计算的字距调整(据我所知),计算让我减少了 1-2 个空格,我只需再次测量字符串并从中添加或减去空格,直到它到达maxNameWidth与其方向相反的一侧;例如。如果太短则添加一个空格,再次测量并查看是否结束maxNameWidth,如果是则停止,反之亦然。

完整代码:

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);

}

输出(用 14pt Arial 粘贴到某处以查看对齐方式):

a                     12345678910
as                   12345678910
asd                 12345678910
asdf                12345678910
asdfg              12345678910

推荐阅读