Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中绘制具有特定大小的字符_Java_Graphics_Fonts_Character - Fatal编程技术网

在Java中绘制具有特定大小的字符

在Java中绘制具有特定大小的字符,java,graphics,fonts,character,Java,Graphics,Fonts,Character,我有一个显示10x10单元格网格的Java编程。在每个单元格中,我想画一个字符,让它占据整个单元格 我目前正在使用以下代码,但大小不太合适 graphics.setFont(new Font("monospaced", Font.PLAIN, 12)); for(int x = 0; x < GRID_WIDTH; x++) { for(int y = 0; y < GRID_HEIGHT; y++) { graphics.drawString(Charac

我有一个显示10x10单元格网格的Java编程。在每个单元格中,我想画一个字符,让它占据整个单元格

我目前正在使用以下代码,但大小不太合适

graphics.setFont(new Font("monospaced", Font.PLAIN, 12));

for(int x = 0; x < GRID_WIDTH; x++) {
    for(int y = 0; y < GRID_HEIGHT; y++) {
        graphics.drawString(Character.toString(grid[x][y]), x * CELL_WIDTH, (y + 1) * CELL_HEIGHT);
    }
}
graphics.setFont(新字体(“单间距”,Font.PLAIN,12));
对于(int x=0;x

Java中是否有任何方法可以绘制10x10(或
CELL\u WIDTH
x
CELL\u HEIGHT
)字符?

我在一个项目中构建了这些方法,我在阅读此问题=D时碰巧打开了该项目。请注意,该方法的大小应该适合您的特定情况。默认大小为130,这对于您的案例来说可能太高了。您可以根据需要对其进行调整,但这演示了基本原理。在您的情况下,请这样使用它们:

Font baseFont = new Font("monospaced", Font.PLAIN, 12);
for(int x = 0; x < GRID_WIDTH; x++) {
   for(int y = 0; y < GRID_HEIGHT; y++) {
       graphics.setFont(pickOptimalFontSize(graphics, Character.toString(grid[x][y]), CELL_WIDTH, CELL_HEIGHT, baseFont));
       drawString(graphics, Character.toString(grid[x][y]), x * CELL_WIDTH, (y + 1) * CELL_HEIGHT, "left", "center");
   }
}



public static void drawString(Graphics g, String str, double x, double y, String hAlign, String vAlign) {

    FontMetrics metrics = g.getFontMetrics();
    double dX = x;
    double dY = y;
    if(hAlign == null || "left".equals(hAlign.toLowerCase())) {
    } else if("center".equals(hAlign.toLowerCase())) {
        dX -= metrics.getStringBounds(str, g).getWidth()/2;
    } else if("right".equals(hAlign.toLowerCase())) {
        dX -= metrics.getStringBounds(str, g).getWidth();
    }


    if(vAlign == null || "bottom".equals(vAlign.toLowerCase())) {
    } else if("center".equals(vAlign.toLowerCase())) {
        dY += metrics.getAscent()/2;
    } else if("top".equals(vAlign.toLowerCase())) {
        dY += metrics.getAscent();
    }

    g.drawString(str, (int)dX, (int)dY);
}

private static Font pickOptimalFontSize (Graphics2D g, String title, int width, int height, Font baseFont) {
    Rectangle2D rect = null;

    float fontSize = 130; //initial value
    Font font;
    do {
        fontSize-=1;
        font = baseFont.deriveFont(fontSize);
        rect = getStringBoundsRectangle2D(g, title, font);
    } while (rect.getWidth() >= width || rect.getHeight() >= height);
    return font;
}

public static Rectangle2D getStringBoundsRectangle2D (Graphics g, String title, Font font) {
    g.setFont(font);
    FontMetrics fm = g.getFontMetrics();
    Rectangle2D rect = fm.getStringBounds(title, g);
    return rect;
}
Font-baseFont=新字体(“等距”,Font.PLAIN,12);
对于(int x=0;x=width | | rect.getHeight()>=height);
返回字体;
}
公共静态矩形2D getStringBoundsRectangle2D(图形g、字符串标题、字体){
g、 setFont(字体);
FontMetrics fm=g.getFontMetrics();
矩形2d rect=fm.getStringBounds(标题g);
返回矩形;
}

我找到了一个我想要的解决方案:我创建了一个名为
CharacterImageGenerator
的类,该类生成(并缓存)
图像
s个字符。然后,每当我想画一个角色时,我就绘制并缩放这些图像

public class CharacterImageGenerator {

    private FontMetrics metrics;
    private Color color;
    private Map<Character, Image> images;

    public CharacterImageGenerator(FontMetrics metrics, Color color) {
        this.metrics = metrics;
        this.color = color;
        images = new HashMap<Character, Image>();
    }

    public Image getImage(char c) {
        if(images.containsKey(c))
            return images.get(c);

        Rectangle2D bounds = new TextLayout(Character.toString(c), metrics.getFont(), metrics.getFontRenderContext()).getOutline(null).getBounds();
        if(bounds.getWidth() == 0 || bounds.getHeight() == 0) {
            images.put(c, null);
            return null;
        }
        Image image = new BufferedImage((int)bounds.getWidth(), (int)bounds.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
        Graphics g = image.getGraphics();
        g.setColor(color);
        g.setFont(metrics.getFont());
        g.drawString(Character.toString(c), 0, (int)(bounds.getHeight() - bounds.getMaxY()));

        images.put(c, image);
        return image;
    }
}
然后缩放并绘制到我想要的大小

private void drawCharacter(int x, int y, char c) {
    graphics.drawImage(characterGenerator.getImage(c), PADDING + (x * TILE_WIDTH), PADDING + (y * TILE_HEIGHT), TILE_WIDTH, TILE_HEIGHT, null);
}

您需要计算单个字符的宽度和高度,以确定单元格中实际适合的字体大小。由于每个字体和字体的每个字符具有/可以具有不同的特征,因此每个字符和字体的特征都会发生变化。通读更多细节如果这是我的程序,我会使用JLabel或JTextField,并给它一个所需字体大小的字符,然后让版面管理员决定如何最佳调整字体大小。看看你心中是否有一个特定的大小,然后你可以通过调整正确方向的大小,然后检查高度和宽度,直到你已经足够接近它。我更想弄清楚如何将一个字符缩放为10×10的正方形而不是找到适合该单元格的字体大小。
fm.getStringBounds
似乎给出了奇怪的结果,因为它为字体大小9提供了10.47的高度,但当我查看绘制的内容时,高度是6像素。这会导致整个
pickOptimalFontSize
方法选择一个比所需尺寸小得多的尺寸。@DanielGibbs FontMetrics使用起来非常奇怪,对于某些字体,它们不会返回完美的匹配,特别是当您谈论1px的差异时。请注意,pickOptimalFontSize中的循环一次递增1个大小。如果要使用这些微小的增量,则应设置fontSize=16;。。。。。fontSize-=.2f;尝试调整该方法。就像我说的,它是为一个需要大字体的特定项目而构建的。使用AWT时,需要降低数值。增量不是问题所在。问题在于字体度量返回的边界是错误的。他们说一个角色的身高是6,而它的身高是10.47。
private void drawCharacter(int x, int y, char c) {
    graphics.drawImage(characterGenerator.getImage(c), PADDING + (x * TILE_WIDTH), PADDING + (y * TILE_HEIGHT), TILE_WIDTH, TILE_HEIGHT, null);
}