Java图形随机文本 [英] Java graphics random text
问题描述
我正在尝试使用drawString(word, x, y)
和x,y值随机,根据BufferedImage上的单词频率使用fontSize
绘制随机文本.不幸的是,它绘制了重叠的随机文本.图像帧大小为1200 x 650,x,y的随机数在这些值之间.这是我的代码:
I'm trying to draw random text with fontSize
based on word frequency on the BufferedImage using the drawString(word, x, y)
with random x,y values. Unfortunately it draws the random text that is overlaping. The image frame size is 1200 x 650 and the random numbers for x, y are between these values. Here's my code:
Random rand = new Random();
Font f = getRandomFont(fontSize);
FontMetrics metrics = graphics.getFontMetrics(f);
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
int textwidth = (int)(f.getStringBounds(word, frc).getWidth());
int textheight = (int)(f.getStringBounds(word, frc).getHeight());
graphics.setColor(Color.red);
graphics.setFont(f);
int x = textwidth + rand.nextInt(800);
int y = -textheight + rand.nextInt(800);
graphics.drawString(word, x , y );
推荐答案
首先,在基线"周围绘制字体,即y
位置代表基线,因此文本可以在其上方和下方生长.它...
First, fonts are drawn around the "base line", that is, the y
position represents the baseline, so the text can grow above it and below it...
因此,您应该使用FontMetrics#getAscent
第二,您需要跟踪所有先前绘制过的文本位置,可以使用FontMetrics#getStringBounds
来实现,它返回一个Rectangle2D
并保留一个列表,您可以对其进行迭代检查如果新文本与其他任何文本相交,例如...
Second, you need to keep track of all the previous locations text was painted, you could do this by using FontMetrics#getStringBounds
, which returns a Rectangle2D
and simply keep a list of this, which you can iterate over to check if the new text intersects any other, as an example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
public TestPane() {
img = new BufferedImage(1200, 650, BufferedImage.TYPE_INT_ARGB);
try (BufferedReader br = new BufferedReader(new FileReader(new File("Words.txt")))) {
List<String> words = new ArrayList<>(25);
String text = null;
System.out.println("Read");
while ((text = br.readLine()) != null) {
words.add(text);
}
System.out.println("Loaded " + words.size());
Collections.sort(words);
Random rnd = new Random();
Font font = getFont();
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, 1200, 650);
List<Rectangle2D> used = new ArrayList<>(25);
for (String word : words) {
int size = rnd.nextInt(37) + 11;
Font drawFont = font.deriveFont((float) size);
FontMetrics fm = g2d.getFontMetrics(drawFont);
Rectangle2D bounds = fm.getStringBounds(word, g2d);
System.out.println("Positing " + word);
do {
int xPos = rnd.nextInt(1200 - (int)bounds.getWidth());
int yPos = rnd.nextInt(650 - (int)bounds.getHeight());
bounds.setFrame(xPos, yPos, bounds.getWidth(), bounds.getHeight());
} while (collision(used, bounds));
used.add(bounds);
g2d.setFont(drawFont);
g2d.setColor(Color.BLACK);
g2d.drawString(word, (float)bounds.getX(), (float)bounds.getY() + fm.getAscent());
g2d.setColor(Color.RED);
g2d.draw(bounds);
}
g2d.dispose();
} catch (IOException exp) {
exp.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(1200, 650);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(img, 0, 0, this);
g2d.dispose();
}
protected boolean collision(List<Rectangle2D> used, Rectangle2D bounds) {
boolean collides = false;
for (Rectangle2D check : used) {
if (bounds.intersects(check)) {
collides = true;
break;
}
}
return collides;
}
}
}
红色矩形仅用于演示目的,您可以摆脱它们.
The red rectangles are just for demonstration purposes and you can get rid of those.
但是,这确实表现出一个小问题,并非所有文本都填充了所有矩形.
This does, however, demonstrate a small problem, not all the text fills all of the rectangle.
更复杂的解决方案是使用TextLayout
生成文本的Shape
,这将使单词分组在一起非常紧密.
A more complex solution would be to use a TextLayout
to generate a Shape
of the text, which would allow words to be grouped much closed together.
看看将图像分配给字符串演示如何生成
这篇关于Java图形随机文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!