c# - 如何垂直对齐非等宽文本
问题描述
我正在尝试使用可变宽度字体创建两列左对齐的文本。我目前的流程:
- 测量将进入第一列的字符串
- 从所述第一列的最大宽度中减去其宽度以获得差值
- 将其除以单个空格的宽度以获得所需的空格数
- 用必要数量的空格右填充结果
这在我看来合乎逻辑,但输出看起来像这样(使用可变宽度字体):
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
...
解决方案
终于明白了。但是我认为这个解决方案是令人作呕的垃圾,所以我会一直打开这个问题,直到有人有更好/更少的蛮力方法。
基本上,由于无法计算的字距调整(据我所知),计算让我减少了 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
推荐阅读
- java - 为什么某些 Java 货币格式的前缀和后缀以类似空格的字符而不是空格结尾?
- python - 具有依赖条件的嵌套列表理解
- functional-programming - 如何重构带有过度嵌套的 case 语句
- php - 根据用户类型创建一个页面以重定向到我的会话的不同页面,但只有第二个标头位置正在重定向
- python - 你将如何编写这个 pymongo/mongodb 查询,在某种程度上它包含数组中的字符串?(包括图片)
- meteor - Meteorjs - 迭代用户数据的常规方法
- python - 使用 Tk.mainloop() 呈现 tk 实例
- postgresql - 隔离级别和显式锁定:意外的序列化错误
- android - ObjectAnimator 不采用 Int 值?
- mysql - MySQL 5.6.39 - 这些语句是否适用于存储过程?