Olá, estou tendo um pequeno problema com um código, eu fiz uma classe que desenha uma caixa e escreve coisas dentro; para saber até quando vai escrever e depois pular de linha (para caber na caixa), eu uso o FontMetrics. Acontece que para usa o FontMetrics, precisa do Graphics2D, e para criar (e instanciar) o Graphics2D, precisa do BufferedImage que vou usar. Mas para criar o BufferedImage, eu preciso das dimensões, e, embora eu saiba a largura, que é definida, eu preciso saber também a altura; mas para descobrir a altura, eu preciso usar o FontMetrics para ver quantas linhas vai ter. Eu tentei resolver esse problema de dois jeitos, os dois dão certo mas geram outro problema. Primeiro eu tentei criar uma BufferedImage nova, de dimensões 1x1, e outro Graphics2D, somente para criar o FontMetrics; deu certo, só que, no final, a conta não dava muito certo, as vezes ficava uma ou duas palavras "a mais" e passava do limite da borda. Eu pensei que o problema fosse outra coisa, mas eu chequei várias vezes e estava tudo certo, só tinha essa gambiarra de estranho. Aí eu pensei, se para criar o FontMetrics precisa de um Graphics2D (eu tentei criar só com a fonte e não deu), deve ser por que o tamanho da fonte muda ligeiramente dependendo do Graphics2D, e isso estaria causando a distorção. Aí eu tentei um segundo método, na verdade há uma altura máxima para o box, se passar dessa altura eu coloco barra de rolagem, então nesse método eu criava a BufferedImage antes com a altura máxima, se ele fosse menor, fica um espaço transparente embaixo (acho que essa não deve ser a solução certa também, pois gasta espaço a toa), também dá certo mas continua passando da borda. Na verdade eu tinha conseguido tirar esse erro simplesmente diminuindo a largura quando eu vou checar se cabe na linha (por exemplo, se eu checava if text.length() <= width - 10 (<-- esse 10 é das bordas), eu colocava if text.length() <= width - 50 mudando 10 por um número que eu fui tentando até caber tudo). Porém, eu descobri depois que isso também não dava certo, pois conforme eu aumentava o tamanho do box (até então estava tentando com boxes todos do mesmo comprimento), esse valor que precisava por (50) aumentava de uma maneira estranha e imprevisível. E, além disso, esse método também é uma gambiarra, não tem nenhuma razão para diminuir além dos 10 que eu já tirei das bordas (sim, dos dois lados). Então, não sei se o erro é no Graphics2D ou no que, mas eu não consigo achar e gostaria de saber se alguém poderia me ajudar, vou passar a classe que cria esses Boxes com texto dentro.
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public final class Hint extends gameObject {
Box box;
String text;
ArrayList palavras, linhas, linhasVisiveis, coloredLines, specialLines, imgs;
Font font;
FontMetrics metrics;
boolean scroll;
static final int maxHeight = 250;
int primLinha, ultimaLinha, actualHeight, linhasFinais;
public Hint(String txt, int pw, ArrayList images) {
coloredLines = new ArrayList();
specialLines = new ArrayList(); //specialLines.get(0): int[LINHA] = NOVO TAMANHO
imgs = images;
text = txt;
width = pw;
palavras = linhas = new ArrayList();
font = new Font("Domestic Manners",Font.PLAIN,10);
palavras = separar(text);
//Até aqui eu só separei as palavras do texto, agora começa a parte em que eu acho que há um problema
BufferedImage newBuff = new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB); //aqui eu crio outro BufferedImage e Graphic2D como falei
Graphics2D g = newBuff.createGraphics();
g.dispose();
metrics = g.getFontMetrics(font);
int i = 0;
//aqui é o código para separar as palavras em linhas (ele adiciona as palavras numa linha até o tamanho de acordo com o FontMetrics der maior que a largura)
while (i < palavras.size()) {
String linha = "";
boolean end = false;
while (!end)
if (i < palavras.size()) { //aqui tem uns códigos que criei, esse pula a linha
if (((String) palavras.get(i)).equals("</n>")) {
linhas.add(linha);
linha = "";
i++;
} else if (((String) palavras.get(i)).equals("</c")) { //para mudar a cor da linha, você usa </c 3, por exemplo, sendo 3 o número da cor
int[] cL = new int[2];
cL[0] = linhas.size();
cL[1] = Integer.parseInt((String) palavras.get(i+1));
coloredLines.add(cL);
i += 2;
} else if (((String) palavras.get(i)).equals("</i")) { //aqui para acrescentar uma imagem. o problema não está aí eu acho, pois o erro ocorre mesmo nas linhas sem cor especial ou imagem.
int[] sL = new int[5];
sL[2] = metrics.stringWidth(linha) + 5;
for (int j = -2; metrics.stringWidth(" ")*j <= ((BufferedImage)imgs.get(Integer.parseInt((String) palavras.get(i+1)))).getWidth(); j++)
linha = linha + " ";
i += 2;
if (((BufferedImage)imgs.get(Integer.parseInt((String) palavras.get(i+1)))).getHeight() > metrics.getHeight())
sL[1] = ((BufferedImage) imgs.get(sL[4])).getHeight()+1;
else
sL[1] = metrics.getHeight();
sL[0] = linhas.size()-1;
sL[4] = Integer.parseInt((String) palavras.get(i+1));
specialLines.add(sL);
//aqui é onde acho que está o problema, como falei estou comparando a linha atual mais o que vou adicionar com a largura -10 das margens
} else if (metrics.stringWidth(linha + " " + ((String) palavras.get(i))) < width - 10) {
linha = linha + " " + ((String) palavras.get(i));
i++;
} else //se couber eu adiciono, senão eu acabo a linha e vai para a próxima
end = true;
} else
end = true;
linhas.add(linha);
}
//aqui acho que não é mais o problema
linhasFinais = 0; int alturaTotal = 0, essaLinha;
boolean end = false;
while (!end) {
essaLinha = metrics.getHeight();
for (int j = 0; j < specialLines.size(); j++)
if (((int[]) specialLines.get(j))[0] == linhas.size()-1 - linhasFinais) {
essaLinha = ((int[]) specialLines.get(j))[1];
break;
} else if (((int[]) specialLines.get(j))[0] > linhas.size()-1 - linhasFinais)
break;
if (alturaTotal + essaLinha <= maxHeight) {
alturaTotal += essaLinha;
linhasFinais++;
} else
end = true;
}
height = getHeight(0);
actualHeight = height;
rolar(0);
}
public int getHeight(int linhaInicial) {
int h = metrics.getHeight() * (linhas.size() - linhaInicial) + 10;
for (int j = linhaInicial; j < specialLines.size(); j++)
h += ((int[]) specialLines.get(j))[1] - metrics.getHeight();
return h;
}
public void move(int pox, int poy, int tex, int tey) {
if (pox > tex/2)
x = pox - width;
else
x = pox;
if (poy > tey/2)
y = poy - height;
else
y = poy;
}
public Color getColor(int num) {
if (num == 0)
return Color.YELLOW;
else if (num == 1)
return Color.GREEN;
else if (num == 2)
return Color.BLUE;
else if (num == 3)
return Color.RED;
else if (num == 4)
return Color.PINK;
else
return Color.GRAY;
}
public ArrayList separar(String text) {
ArrayList ar = new ArrayList();
int preI = -1;
for(int i = 0; i < text.length(); i++)
if (text.charAt(i) == ' ') {
ar.add(text.substring(preI+1, i));
preI = i;
}
ar.add(text.substring(preI+1, text.length()));
return ar;
}
public ArrayList pegarLinhas(int linhaInicial){
ArrayList linVis = new ArrayList();
int qtasLinhas = 0, alturaTotal = 0, essaLinha;
boolean end = false;
while (!end) {
essaLinha = metrics.getHeight();
for (int j = 0; j < specialLines.size(); j++)
if (((int[]) specialLines.get(j))[0] == linhaInicial + qtasLinhas) {
essaLinha = ((int[]) specialLines.get(j))[1];
break;
} else if (((int[]) specialLines.get(j))[0] > linhaInicial + qtasLinhas)
break;
if (alturaTotal + essaLinha <= maxHeight) {
alturaTotal += essaLinha;
qtasLinhas++;
} else
end = true;
}
for(int i = linhaInicial; i < linhaInicial + qtasLinhas; i++)
linVis.add(linhas.get(i));
return linVis;
}
public void rolar (int quanto) {
if (actualHeight <= maxHeight) {
linhasVisiveis = linhas;
scroll = false;
primLinha = 0;
ultimaLinha = linhas.size()-1;
} else {
height = maxHeight;
scroll = true;
if (quanto != 0)
primLinha += quanto;
else primLinha = 0;
if (primLinha < 0)
primLinha = 0;
if (primLinha > linhas.size() - linhasFinais)
primLinha = linhas.size() - linhasFinais;
linhasVisiveis = pegarLinhas(primLinha);
ultimaLinha = primLinha + linhasVisiveis.size();
}
if (scroll) {
objBuffer = new BufferedImage(width+10,height,BufferedImage.TYPE_INT_ARGB);
box = new Box(0,0,width+10,height,actualHeight,primLinha,linhas.size()-1);
} else {
objBuffer = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
box = new Box(0,0,width,height);
}
Graphics2D b = objBuffer.createGraphics();
int py = 5;
b.drawImage(box.objBuffer,box.x,box.y,null);
for (int j = 0; j < linhasVisiveis.size(); j++) {
b.setColor(Color.white);
for (int l = 0; l < coloredLines.size(); l++)
if (((int[])coloredLines.get(l))[0] == j + primLinha) {
b.setColor(getColor(((int[])coloredLines.get(l))[1]));
break;
} else if (((int[])coloredLines.get(l))[0] > j + primLinha)
break;
b.drawString((String) linhasVisiveis.get(j), 5, py+metrics.getHeight()/2);
py += metrics.getHeight();
for (int k = 0; k < specialLines.size(); k++)
if (((int[]) specialLines.get(k))[0] == j + primLinha) {
((int[]) specialLines.get(k))[3] = py - 5;
py += ((int[]) specialLines.get(k))[1] - metrics.getHeight();
break;
} else if (((int[]) specialLines.get(k))[0] > j + primLinha)
break;
}
for (int k = 0; k < specialLines.size(); k++)
if ((((int[]) specialLines.get(k))[0] > primLinha) && (((int[]) specialLines.get(k))[0] < ultimaLinha)) {
BufferedImage aBuffer = (BufferedImage)imgs.get(((int[]) specialLines.get(k))[4]);
int psx = ((int[]) specialLines.get(k))[2];
int psy = ((int[]) specialLines.get(k))[3];
b.drawImage(aBuffer, psx, psy, null);
}
b.dispose();
}
}
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
public class Box extends gameObject {
String bul, bur, bdl, bdr, bu, bl, br, bd, bc;
public Box(int px, int py, int pw, int ph){
x = px;
y = py;
width = pw;
height = ph;
path = System.getProperty("user.dir") + "\src\images\box\";
bul = path + "bul.png";
bur = path + "bur.png";
bdl = path + "bdl.png";
bdr = path + "bdr.png";
bu = path + "bu.png";
bl = path + "bl.png";
br = path + "br.png";
bd = path + "bd.png";
bc = path + "bc.png";
objBuffer = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics2D b = objBuffer.createGraphics();
b.drawImage(new ImageIcon(bul).getImage(),0,0,null);
b.drawImage(new ImageIcon(bur).getImage(),width-4,0,null);
for(int i = 4; i < width-4; i += 4)
b.drawImage(new ImageIcon(bu).getImage(),i,0,null);
BufferedImage buf = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);;
Graphics2D gbuf = buf.createGraphics();
gbuf.drawImage(new ImageIcon(bl).getImage(),0,0,null);
gbuf.drawImage(new ImageIcon(br).getImage(),width-4,0,null);
for(int i = 4; i < width-4; i += 4)
gbuf.drawImage(new ImageIcon(bc).getImage(),i,0,null);
gbuf.dispose();
for(int i = 4; i < height-4; i += 4)
b.drawImage(buf, 0, i, null);
b.drawImage(new ImageIcon(bdl).getImage(),0,height-4,null);
b.drawImage(new ImageIcon(bdr).getImage(),width-4,height-4,null);
for(int i = 4; i < width-4; i += 4)
b.drawImage(new ImageIcon(bd).getImage(),i,height-4,null);
b.dispose();
}
public Box(int px, int py, int pw, int ph, int ah, int lA, int qL){
x = px;
y = py;
width = pw;
height = ph;
path = System.getProperty("user.dir") + "\src\images\box\";
bul = path + "bul.png";
bur = path + "bur.png";
bdl = path + "bdl.png";
bdr = path + "bdr.png";
bu = path + "bu.png";
bl = path + "bl.png";
br = path + "br.png";
bd = path + "bd.png";
bc = path + "bc.png";
String cup = path + "cup.png";
String c = path + "c.png";
String cd = path + "cd.png";
objBuffer = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
Graphics2D b = objBuffer.createGraphics();
b.drawImage(new ImageIcon(bul).getImage(),0,0,null);
b.drawImage(new ImageIcon(bur).getImage(),width-4,0,null);
for(int i = 4; i < width-4; i += 4)
b.drawImage(new ImageIcon(bu).getImage(),i,0,null);
b.drawImage(new ImageIcon(cup).getImage(),width-14,0,null);
BufferedImage buf = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);;
Graphics2D gbuf = buf.createGraphics();
gbuf.drawImage(new ImageIcon(bl).getImage(),0,0,null);
gbuf.drawImage(new ImageIcon(br).getImage(),width-4,0,null);
for(int i = 4; i < width-4; i += 4)
gbuf.drawImage(new ImageIcon(bc).getImage(),i,0,null);
gbuf.drawImage(new ImageIcon(c).getImage(),width-14,0,null);
gbuf.dispose();
for(int i = 4; i < height-4; i += 4)
b.drawImage(buf, 0, i, null);
b.drawImage(new ImageIcon(bdl).getImage(),0,height-4,null);
b.drawImage(new ImageIcon(bdr).getImage(),width-4,height-4,null);
for(int i = 4; i < width-4; i += 4)
b.drawImage(new ImageIcon(bd).getImage(),i,height-4,null);
b.drawImage(new ImageIcon(cd).getImage(),width-14,height-4,null);
b.dispose();
}
}
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class gameObject {
int x, y, width, height, maxheight;
double speed, speedx, speedy, ang;
BufferedImage objBuffer;
AffineTransform angulo;
String path;
Hint hint; boolean temHint, mostrarHint;
public void draw(Graphics2D g) {
g.drawImage(objBuffer,x,y,null);
}
public void addHint(String txt, int pw) {
hint = new Hint(txt, pw);
temHint = true;
}
public void addHint(String txt, int pw, ArrayList imgs) {
hint = new Hint(txt, pw, imgs);
temHint = true;
}
public void moveHint(int px, int py, int tx, int ty) {
if (temHint)
hint.move(px, py, tx, ty);
}
public void mostrarHint(boolean b) {
if (temHint) {
if (!mostrarHint && b)
hint.rolar(0);
}
mostrarHint = b;
}
}
String desc = "</c 0 Anão </n> DESCRIÇÃO </n> Habilidades: </n> </i 0 </c 0 Visão no escuro </n> Permite enchegar por 18m em lugares sem qualquer iluminação. </n> </i 1 </c 0 Resistência a Magia </n> Você é mais resistente a magia do que o normal. Recebe mais dois de bônus de Vigor em qualquer teste de resistência a magia. </n> </i 2 </c 0 Resistência a Veneno </n> Você tem mais resistência contra veneno do que o normal. Receba +2 de Vigor em testes de resistência contra veneno. </n> </i 3 </c 0 Bom em avaliação </n> Você possui um talento inato que leh permite melhor decidir o valor de mercadorias. Receba +2 de bônus em testes de avaliação. </n> </i 4 </c 0 Esquiva contra Gigantes </n> Depois de muito batalhar contra inimigos do tipo gigante, você adquiriu +4 de Bônus de Desvio contra essas criaturas. </n> </i 5 </c 0 Ataque contra Orcs e Globinóides </n> Depois de muito batalhar contra Orcs e Globinóides, você adquiriu +1 de Bônus de Atauqe contra essas criaturas. </n> </n> </n> </n> </n> </n> Teste!";
ArrayList imgs = new ArrayList();
//aí adicione as BufferedImage necessárias, na ordem (primeiro a que vai onde tem </i 0, depois a </i 1, etc)
Hint hint = new Hint(desc, 500, imgs);