英文:
I can't center text in java swing
问题
我正在为我的游戏制作自定义组件,我尝试了在Stack Overflow中找到的所有方法,但无论如何我都无法将文本放置在矩形的中心。我甚至阅读了所有关于使用Java文本API的文档。
有人能向我解释如何在Java Swing中一劳永逸地将文本对齐到中心(矩形的中心、框架的中心或其他任何位置)吗?这不是重复的问题,因为在Stack Overflow的其他所有问题中,我都没有得到有效的解决方案。
到目前为止,我已经使用了FontMetrics,我使用了stringWidth()方法测量宽度,使用ascent测量了高度(它们都不准确)。
// ... (其余代码略)
if (text != null) {
FontMetrics fm = g.getFontMetrics();
int textX = x + (width / 2) - (fm.stringWidth(text) / 2);
int textY = y + ((height - fm.getHeight()) / 2) + fm.getAscent();
g.setFont(font);
g.setColor(Color.white);
g.drawString(text, textX, textY);
}
// ... (其余代码略)
英文:
I'm making custom components for my game and I tried everything I found in Stack Overflow and no matter what I still can't place text in the center of a rectangle. I even read all the documentation of working with java text API.
Can anyone explain to me how to align text to the center (Center of rect or frame or anything) in java swing once and for all? This is not a duplicate question because in all the other questions on Stack Overflow I did not get a solution that works.
So far I have used FontMetrics and I measured the width using stringWidth() method and the height using ascent (None of them are accurate).
package com.isi.uicomponents;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import com.isi.core.Game;
import com.isi.states.GameState;
public class Button extends UIComponent {
private Font font;
private String text;
public Button(Game game, GameState state, int x, int y, int width, int height, String text) {
super(game, state, x, y, width, height);
font = new Font("Arial", Font.BOLD, 20);
this.text = text;
}
public Button(Game game, GameState state, int x, int y, int width, int height) {
super(game, state, x, y, width, height);
text = null;
}
public String getText() {
return text;
}
@Override
public void tick() {
}
@Override
public void draw(Graphics2D g) {
g.setColor(fillColor);
g.fillRect(x, y, width, height);
g.setColor(boundsColor);
g.draw(bounds);
if (text != null) {
FontMetrics fm = g.getFontMetrics();
int textX = x + (width / 2) - (fm.stringWidth(text) / 2);
int textY = y + ((height - fm.getHeight()) / 2) + fm.getAscent();
g.setFont(font);
g.setColor(Color.white);
g.drawString(text, textX, textY);
}
}
}
// =============================================
package com.isi.uicomponents;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import com.isi.core.Game;
import com.isi.states.GameState;
public abstract class UIComponent {
public final static Color DEFAULT_BOUNDS_COLOR = Color.white;
public final static Color DEFAULT_FILL_COLOR = Color.gray;
protected Game game;
protected GameState state;
protected int x;
protected int y;
protected int width;
protected int height;
protected Rectangle bounds;
protected Color boundsColor;
protected Color fillColor;
public UIComponent(Game game, GameState state, int x, int y, int width, int height) {
this.game = game;
this.state = state;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
bounds = new Rectangle(x, y, width, height);
boundsColor = DEFAULT_BOUNDS_COLOR;
fillColor = DEFAULT_FILL_COLOR;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
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 Rectangle getBounds() {
return bounds;
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
public Color getBoundsColor() {
return boundsColor;
}
public void setBoundsColor(Color boundsColor) {
this.boundsColor = boundsColor;
}
public Color getFillColor() {
return fillColor;
}
public void setFillColor(Color fillColor) {
this.fillColor = fillColor;
}
public abstract void tick();
public abstract void draw(Graphics2D g);
}
// =============================================
package com.isi.states;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import com.isi.core.Game;
import com.isi.tools.ImageLoader;
import com.isi.uicomponents.Button;
import com.isi.uicomponents.UIComponent;
public class MainMenuState extends GameState {
private static BufferedImage bg = ImageLoader.load("Main Menu Background.jpg");
// Background coordinates for animation
private int x;
private int y;
// MainMenu components array
private ArrayList<UIComponent> components;
public MainMenuState(Game game) {
super(game);
x = 0;
y = 0;
components = new ArrayList<UIComponent>();
components.add(new Button(game, this, game.getWidth() / 2 - 80 / 2, game.getHeight() / 2 - 50 / 2, 80, 50, "Play"));
}
public ArrayList<UIComponent> getComponents() {
return components;
}
public void tick() {
y = y >= game.getHeight() ? 0 : y + 2;
}
public void draw(Graphics2D g) {
g.drawImage(bg, 0, -game.getHeight() + y, game.getWidth(), game.getHeight(), null);
g.drawImage(bg, x, y, game.getWidth(), game.getHeight(), null);
for (int i = 0; i < components.size(); i++) {
components.get(i).draw(g);
}
}
}
答案1
得分: 1
这已经很接近了,你需要将 x 增加半个宽度,然后减去字符串宽度的一半。另外,在获取字体度量之前,你需要设置字体,否则你会得到现有图形字体的度量。
g.setFont(font);
FontMetrics fm = g.getFontMetrics();
int textX = x + (width / 2) - (fm.stringWidth(text) / 2);
int textY = y + ((height - fm.getHeight()) / 2) + fm.getAscent();
g.setColor(Color.white);
g.drawString(text, textX, textY);
英文:
This is close, you need to increase x by half the width and then reduce by half the string width. You also need to set the font before you get the font metrics otherwise you're getting the metrics of the existing Graphics font.
g.setFont(font);
FontMetrics fm = g.getFontMetrics();
int textX = x + (width / 2) - (fm.stringWidth(text) / 2);
int textY = y + ((height - fm.getHeight()) / 2) + fm.getAscent();
g.setColor(Color.white);
g.drawString(text, textX, textY);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论