如何垂直对齐非等宽文本

时间:2018-04-25 03:14:37

标签: c# .net

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

  1. 测量将进入第一列的字符串
  2. 从所述第一列的最大宽度减去其宽度以获得差异
  3. 将其除以单个空格的宽度以获得所需的空格数
  4. 使用必要的空格数右键填充结果
  5. 这对我来说听起来很合理,但输出看起来像这样(使用可变宽度字体):

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

2 个答案:

答案 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:看来我以前在回答时的想法与众不同。由于我也在尝试学习新事物并寻找新方法,因此我试图得到这个问题的结果。无论如何,这次我走在正确的道路上