我在Java中将一组字符串对齐到一个框的底部时遇到了一些问题。
注意:我使用的
Box
课程不是默认设置> javax.Swing 框!它是一个简单的成本箱,有x,y位置,宽度和高度!
Message
类,可以由我的Allign
类单独对齐。MessageList
个Message
个对象的ArrayList的Allign
对象,可以与Box
类对齐。Allign
对象。 Allign
类使用此框来对齐对象。Box
类,并使用Message
对象进行对齐。(代码片段在页面下方)
Font
对象可以使用不同的Allign
设置。 Message
类可以对齐这些Message
对象。 obtainFontDimension()
类包含一个名为Font
的方法,该方法在首选Message
设置中获取对象的字符串边界。当我们想要将对齐应用于Box
对象时,我创建了一个Allign.applyAllignment(params)
对象,其中包含x,y位置以及宽度和高度。通过调用Message
,将应用计算来对齐Box
中的Message
对象和MessageList
的dx,dy(绘制x,y位置) )将被设定。
直到这里工作正常。
现在我创建一个Message
对象并向其添加一些(Message
个对象。当对它应用对齐时,它将运行它包含的obtainFontDimensions()
个对象,并将调用它们上的int listHeight
。这些字符串的高度将相加,并将结果转换为字符串的总高度(Message
)。要获得每个Box
对象的绘图位置,我们将listHeight
的y位置放在我们想要对齐的位置。首先,我们删除Box
' sy位置的Box
:
现在我们得到了第一个String的偏移量。在应用底部对齐时,它只会将Message
的高度添加到偏移量。最后,通过将当前Message
对象高度添加到te偏移量,为下一个MessageList
对象设置偏移量。下一次迭代的时间,直到ArrayList完全计算完毕。这应该导致以下结果:
将对齐应用于public class Window()
{
public void draw(Graphics2D g2d)
{
Box contentBox = new Box(100, 100, 300, 300);
Message loadTitle = new Message("This is a testing TITLE", Colors.ORANGE, Fonts.LOADING_TITLE, false);
Message loadDescription = new Message(loadString, Colors.RED, Fonts.LOADING_DESCRIPTION, false);
Message loadTip = new Message("This is a random TIP!", Colors.RED, Fonts.LOADING_DESCRIPTION, false);
Message loadRelease = new Message("Planned game release 2939!", Colors.RED, Fonts.LOADING_DESCRIPTION, false);
Message loadSingle = new Message("THIS IS A SINGLE MESSAGE! 2o15", Colors.RED, Fonts.LOADING_DESCRIPTION, false);
MessageList list = new MessageList();
list.add(loadTitle);
list.add(loadDescription);
list.add(loadTip);
list.add(loadRelease);
list.add(loadSingle);
Allign.applyAllignment(g2d, Allignment.BOTTOM_RIGHT, list, loadBox);
loadBox.testDraw(g2d);
loadTitle.draw(g2d);
loadDescription.draw(g2d);
loadTip.draw(g2d);
loadRelease.draw(g2d);
loadSingle.draw(g2d);
}
}
public class Message
{
private String text;
private Color color;
private Font font;
private int dx, dy;
private int width, height;
private Rectancle2D vb; // temp
public Message(String text, int x, int y, Color color, Font font)
{
// set text, color, font, x, y..
}
public Rectangle2D obtainFontDimension(Graphics2D g2d)
{
if(font == null){ font = Fonts.DEFAULT; }
g2d.setFont(font);
FontRenderContext frc = g2d.getFontRenderContext();
GlyphVector gv = g2d.getFont().createGlyphVector(frc, text);
Rectangle2D vb = gv.getPixelBounds(null, 0, 0);
this.width = (int)vb.getWidth();
this.height = (int)vb.getHeight();
this.gv = gv; // TEMP for bound drawing
return vb;
}
public void draw(Graphics2D g2d)
{
g2d.setFont(font);
g2d.setColor(color);
g2d.drawString(text, dx, dy);
// TEMP draw bounds
g2d.setColor(new Color(0, 0, 0, 100));
g2d.draw(gv.getPixelBounds(null, dx, dy));
}
}
public class Allign
{
public static enum Allignment
{
BOTTOM_RIGHT
//, etc
}
public static void applyAllignment(Graphics2D g2d, Allignment allignment, Object object, Box box)
{
Point position = null;
Point dimension = null;
if(obj instanceof Message){ // Single Message object }
else if(obj instanceof Message)
{
MessageList messageList = (MessageList) obj;
int listHeight = 0;
for(Message message : messageList.getList())
{
listHeight += message.obtainFontDimension(g2d).getHeight();
}
position = new Point(box.x, box.y-listHeight); // offset Y
for(Message message : messageList.getList())
{
message.setDrawPosition(allign(allignment, position, new Dimension(message.getWidth(), 0), box, true));
position.y += message.getHeight();
}
}
}
private static Point allign(Allignment allignment, Point position, Dimension dimension, Box box, boolean verticalAllign)
{
switch(allignment)
{
case BOTTOM_RIGHT:
position = allignRight(position, dimension, box);
if(!verticalAllign) break;
position = allignBottom(position, dimension, box);
break;
// Rest
}
}
private static Point allignBottom(Point position, Dimension dimension, Box box)
{
return new Point(position.x, position.y+box.height-dimension.height);
}
}
对象时,某些字符串会完美地相互接触(请参见图像上的圆圈B),有些像素会使其他像素的距离更远(参见图像上的圆A1,A2)。接下来,底部仍有一个意外的填充(见图像上的圆圈C)。
(仅限重要部分)
\b(\w+)\s+(?=\1)
答案 0 :(得分:1)
我可以建议这样的实用程序类吗?
public class TextPrinter {
public enum VerticalAlign {
TOP,
MIDDLE,
BOTTOM
}
public enum HorizontalAlign {
LEFT,
CENTER,
RIGHT
}
private Font font;
private Color color;
private int width;
private int height;
private VerticalAlign vAlign = VerticalAlign.TOP;
private HorizontalAlign hAlign = HorizontalAlign.LEFT;
public Font getFont() {
return font;
}
public void setFont(Font font) {
this.font = font;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public VerticalAlign getVerticalAlign() {
return vAlign;
}
public void setVerticalAlign(VerticalAlign vAlign) {
this.vAlign = vAlign;
}
public HorizontalAlign getHorizontalAlign() {
return hAlign;
}
public void setHorizontalAlign(HorizontalAlign hAlign) {
this.hAlign = hAlign;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
private int getOffSetX(int widthText){
int result = 0;
if (hAlign == HorizontalAlign.CENTER){
result = (width - widthText)/2;
} else if (hAlign == HorizontalAlign.RIGHT){
result = width - widthText;
}
return result;
}
private int getOffSetY(int ascent, int descent){
int result = ascent;
if (vAlign == VerticalAlign.MIDDLE){
result = (height + ascent - descent)/2;
} else if (vAlign == VerticalAlign.BOTTOM){
result = height - descent;
}
return result;
}
public void print(Graphics g, String text, int x, int y) {
g.setColor(color);
g.setFont(font);
FontMetrics fm = g.getFontMetrics(font);
int widthText = fm.stringWidth(text);
g.drawString(text, x + getOffSetX(widthText), y + getOffSetY(fm.getAscent(), fm.getDescent()));
}
}
我在扑克游戏中使用它: https://github.com/dperezcabrera/jpoker
答案 1 :(得分:0)
感谢David Perez和VGR的投入!
我已切换回Font指标,抓住了字符串边界的高度。但是,这仅使用基线的高度到最高的上升点。对于正确的底部间距(如在顶部),我添加了下降整数。
public int obtainFontDimension(Graphics2D g2d)
{
if(font == null){ font = Fonts.DEFAULT; }
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics(font);
Rectangle2D sb = fm.getStringBounds(text, g2d);
this.width = (int)sb.getWidth();
this.height = (int)sb.getHeight();
this.descent = (int)fm.getDescent(); // added
tempShape = new Rectangle(width, height+descent); // Temp for drawing bounds
return height;
}
在对齐开始之前,我首先计算MessageList中所有字符串的总高度。总高度是String的高度,包括降序高度。
然后我需要获得每个垂直对齐可能性的偏移高度,我已经添加了。 (TOP,MIDDLE,BOTTOM)
之后,我们通过在每次迭代时将高度和下降添加到偏移量来对每个消息进行对齐,这次禁用垂直对齐,或者它将每个消息水平地重新分配为单个Message对象而不是一组消息,但它确实允许它垂直对齐。
if (obj instanceof MessageList)
{
MessageList messageList = (MessageList) obj;
int listHeight = 0;
for(Message message : messageList.getList())
{
message.obtainFontDimension(g2d);
listHeight += message.getHeight()+message.getDescent();
}
position = new Point(box.x, box.y);
Dimension listDimension = new Dimension(0, listHeight);
if( allignment == Allignment.MIDDLE || allignment == Allignment.MIDDLE_LEFT
|| allignment == Allignment.ABSOLUTE_MIDDLE || allignment == Allignment.MIDDLE_RIGHT)
{
position = allign(Allignment.MIDDLE, position, listDimension, box, true);
}
else if(allignment == Allignment.BOTTOM || allignment == Allignment.BOTTOM_LEFT
|| allignment == Allignment.BOTTOM_CENTER || allignment == Allignment.BOTTOM_RIGHT)
{
position = allign(Allignment.BOTTOM, position, listDimension, box, true);
}
else
{
position = allign(Allignment.TOP, position, listDimension, box, true);
}
for(Message message : messageList.getList())
{
position.y += message.getHeight(); // prepare the offset
message.setDrawPosition(allign(allignment, position, new Dimension(message.getWidth(), 0), box, true));
position.y += message.getDescent(); // add descending offset for next itteration
}
}
使用新界限绘制消息:
public void draw(Graphics2D g2d)
{
g2d.setFont(font);
g2d.setColor(color);
g2d.drawString(text, dx, dy);
// Drawing bounds for testing
g2d.setColor(new Color(0, 0, 0, 100));
shape.setLocation(dx, dy-height);
g2d.draw(tempShape);
}
最终结果:
再次感谢!