View Full Version : [JAVA]Richiesta:Stringa automaticamente a capo
drinkredbull
08-04-2009, 17:35
Ciao ragazzi,
sto da poco tempo affrontando lo sviluppo dei primi applet java, ma ora mi trovo davanti ad un problema.
Avrei la necessità di sapere se con il metodo draw.String() è possibile andare automaticamente a capo quando la stringa arriva alla fine della dimensione dell'applet, oppure se c'è un altro modo e/o un'altro metodo per mandare la stringa automaticamente a capo non ci stia tutta all'interno dell'applet...
Vi ringrazio già a priori per l'aiuto.
TeknoMan
08-04-2009, 17:41
fai un controllo sulla lunghezza della stringa...
Usa java.awt.font.LineBreakMeasurer.
Nella documentazione c'è un esempio d'uso.
Puoi usare AttributedString come AttributedCharacterIterator.
drinkredbull
09-04-2009, 08:53
fai un controllo sulla lunghezza della stringa...
Mi scuso per la mia non completa competenza, ma com'è che posso farlo? Lavoro su un oggetto di tipo String, non su un vettore di char...
Usa java.awt.font.LineBreakMeasurer.
Nella documentazione c'è un esempio d'uso.
Puoi usare AttributedString come AttributedCharacterIterator.
Allora, sono andato a guardare ma la comprensione mi è risultata un po difficoltosa. Comunque in pratica, dovrei usare il LineBreakMeasurer() al posto del drawString(), ed all'interno dovrei inserire come parametro l' AttributedString(miastringa). Il problema è che dovrei inserire anche gli altri due parametri: BreakIterator breakIter e FontRenderContext frc , dei quali non ne ho ben capito l'utilita e come usarli...
http://java.sun.com/j2se/1.4.2/docs/api/java/awt/font/LineBreakMeasurer.html#LineBreakMeasurer(java.text.AttributedCharacterIterator,%20java.awt.font.FontRenderContext)
In'oltre vorrei sapere anche come posso indicare le posizioni esatte in cui stampare la stringa sotto forma di coordinate, come già facevo col drawString, in quanto il mio programma si basa proprio su questo...
Vi ringrazio per il prezioso aiuto che mi state offrendo!
Incollo un esempio commentato.
import java.awt.font.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import javax.swing.*;
public class Main extends JPanel implements Runnable {
public static void main(String[] args) { EventQueue.invokeLater(new Main()); }
public void run() { createAndShowFrame(); }
private String text;
private void createAndShowFrame() {
final JTextField field = new JTextField();
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
text = field.getText();
repaint();
}
});
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.add(this);
window.add(field, BorderLayout.SOUTH);
window.setSize(640, 480);
window.setVisible(true);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Insets insets = getInsets();
int maxWidth = getWidth() - insets.left - insets.right;
int maxHeight = getHeight() - insets.top - insets.bottom;
if(text != null) {
int stringX = 20;
int stringY = 20;//(stringX, stringY) è il punto in cui si vuole disegnare la stringa
int maxX = maxWidth; //maxX è l'ordinata massima della stringa
int maxY = maxHeight; //maxY è la coordinata massima della stringa
drawString(text, (Graphics2D)g, new Rectangle(stringX, stringY, maxX, maxY));
}
}
private void drawString(String s, Graphics2D g, Rectangle area) {
g.setPaint(Color.BLACK);//colore della stringa (se l'AttributedCharacterIterator non definisce colori autonomi)
AttributedCharacterIterator iterator = new AttributedString(s).getIterator(); //data la stringa s ottiene un iteratore su testo formattato
LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, g.getFontRenderContext());
while(measurer.getPosition() < iterator.getEndIndex()) { //measurer.getPosition() tiene traccia del testo finora "estratto" dal measurer
TextLayout painter = measurer.nextLayout(area.width - area.x); //estrae dal measurer un proiettore del testo nella linea corrente
painter.draw(g, area.x, area.y); //disegna il testo estratto in posizione area.x, area.y
area.y += painter.getAscent() + painter.getDescent(); //aggiorna la coordinata per disegnare la linea successiva sotto alla precedente
if(area.y > area.height) { //se è stato consumato tutto lo spazio verticale disponibile
break; //non c'è più spazio per disegnare altre linee
}
}
}
}
A te interessa solo il metodo "drawString". La posizione della stringa è la coppia (area.x, area.y). Il resto fa sì che se la stringa sia spezzata in più linee se la sua lunghezza ecceda la larghezza del componente (meno area.x per tenere allineati i paragrafi).
drinkredbull
09-04-2009, 15:11
Incollo un esempio commentato.
... ... ...
A te interessa solo il metodo "drawString". La posizione della stringa è la coppia (area.x, area.y). Il resto fa sì che se la stringa sia spezzata in più linee se la sua lunghezza ecceda la larghezza del componente (meno area.x per tenere allineati i paragrafi).
Ti ringrazio molto, e riconosco che il codice è fatto bene. Infatti ho provato a copiarlo e poi esegurlo e funziona molto bene, mentre il metodo drawString sembra fatto proprio al caso mio.
Solo che ho provato ad applicare il tutto al mio codice, ma questi appunto non funziona, stampandomi lo sfondo dell'applet, ma non la stringa. Ti posto la parte del mio codice dove stampo, così magari puoi darmi qualche consiglio:
int y; //variabile per posizionare il testo nel modo corretto sull'asse y... ... ...poi verrà modificata via via all'interno del programma...
int x=10;
int maxX = getWidth();
int maxY = getHeight();
... ... ...
public void paint(Graphics g)
{
super.paint(g);
setBackground(colore); //imposta colore sfondo scelto nei parametri
g.setColor(color); //imposta colore testo scelto nei parametri
g.setFont(textFont); //imposta font testo scelto nei parametri
setSize(w,h); //imposta le dimensioni dell'applet
try
{
if (velocita>0) //se la velocita' è >0...
{
for (i=100;i>0;i--) //...stampa dal basso verso l'alto
{
k=i-1;
if(loadArray("prova.txt",k)!=null)
{
drawString(loadArray("prova.txt",k),(Graphics2D)g, new Rectangle(x, y, maxX, maxY));
}
}
}
else //altrimenti,
{
for (i=0;i<100;i++) //stampa dall'alto verso il basso oppure lascia fermo il testo a seconda della scelta della velocita'
{
if(loadArray("prova.txt",i)!=null)
{
drawString(loadArray("prova.txt",i),(Graphics2D)g, new Rectangle(x, y, maxX, maxY));
}
}
}
}
catch(IOException e){g.drawString("Errore" ,200,100);}
}
... ... ...
private void drawString(String s, Graphics2D g, Rectangle area) {
g.setPaint(color);
AttributedCharacterIterator iterator = new AttributedString(s).getIterator(); //data la stringa s ottiene un iteratore su testo formattato
LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, g.getFontRenderContext());
while(measurer.getPosition() < iterator.getEndIndex()) { //measurer.getPosition() tiene traccia del testo finora "estratto" dal measurer
TextLayout painter = measurer.nextLayout(area.width - area.x); //estrae dal measurer un proiettore del testo nella linea corrente
painter.draw(g, area.x, area.y); //disegna il testo estratto in posizione area.x, area.y
area.y += painter.getAscent() + painter.getDescent(); //aggiorna la coordinata per disegnare la linea successiva sotto alla precedente
if(area.y > area.height) { //se è stato consumato tutto lo spazio verticale disponibile
break; //non c'è più spazio per disegnare altre linee
}
}
}
Allora, ti ho messo il metodo paint(), seguito dal tuo drawString.
La variabile velocita' è una variabile che serve a me per vedere in pratica se stampare dall'inizio dal basso all'alto in o all'incontrario. loadArray() invece è un metodo che restituisce una stringa dopo averla letta da un file, lo so che è un po' obsoleto fare la lettura all'interno del paint, ma l'ho messo lì solo momentaneamente e cambierà quando sistemerò il codice. Comunque è accertato che il metodo funziona.
Credo che ci sia qualche incongruenza nel passaggio di parametri o altro...Non riesco a trovare l'errore...
Grazie mille!
A naso direi che i tuoi maxX e maxY sono zero. Per verificarlo possiamo usare il metodo della nonna.
Nel metodo drawString metti come prima istruzione un
System.out.println(area);
e vedi se le coordinate del rettangolo hanno qualcosa di strano.
drinkredbull
09-04-2009, 15:42
A naso direi che i tuoi maxX e maxY sono zero. Per verificarlo possiamo usare il metodo della nonna.
Nel metodo drawString metti come prima istruzione un
System.out.println(area);
e vedi se le coordinate del rettangolo hanno qualcosa di strano.
Ho trovato! Avevi ragione te' erano a 0. Mio errore. Ho sistemato, ed in effetti stampa andando a capo.
Solo che nel mio programma ripeto la stampa più volte con varie stringhe diverse, è il metodo loadarray() che le prende. Ovviamente dopo aver stampato una stringa vado a capo usando il modo un po' "furbo" di incrementare la y di un numero di pixel necessari. Solo che adesso la parte della stringa che mi va' a capo si sovrappone alle stringhe sucessive...
Come posso risolvere il problema?
Grazie tante per il supporto!
Potresti sfruttare un side-effect di drawString.
Il metodo incrementa il valore di area.y per ogni linea che disegna. Capita così che alla fine del metodo il valore di area.y sia anche quello della prima "linea" libera sotto al testo disegnato.
Cioè se dico:
Rectangle area = qualcosa;
drawString(testo, g, area);
...qui area.y è la posizione y della prima linea libera sotto a testo.
In teoria "riciclando" area dovremmo ottenere il disegno non sovrapposto di stringhe diverse:
Rectangle area = qualcosa;
drawString(testo, g, area);
drawString(altroTesto, g, area);
drawString(eccetera, g, area);
Forse :D.
drinkredbull
09-04-2009, 16:05
Potresti sfruttare un side-effect di drawString.
Il metodo incrementa il valore di area.y per ogni linea che disegna. Capita così che alla fine del metodo il valore di area.y sia anche quello della prima "linea" libera sotto al testo disegnato.
Cioè se dico:
Rectangle area = qualcosa;
drawString(testo, g, area);
...qui area.y è la posizione y della prima linea libera sotto a testo.
In teoria "riciclando" area dovremmo ottenere il disegno non sovrapposto di stringhe diverse:
Rectangle area = qualcosa;
drawString(testo, g, area);
drawString(altroTesto, g, area);
drawString(eccetera, g, area);
Forse :D.
Ti ringrazio molto per avermi seguito e consigliato. Probabilmente questa era una buona buona idea, ma sono riuscito a risolvere comunque inserendo l'incremento dell'y dentro il metodo drawString e verificando se sommare o sottrarre con in semplice if.
Finalmente son roiscito a far funzionare il programma e se ci sono riuscito, e sicuramente molto anche merito tuo! Grazie!
banryu79
09-04-2009, 16:19
Ti ringrazio molto per avermi seguito e consigliato. Probabilmente questa era una buona buona idea, ma sono riuscito a risolvere comunque inserendo l'incremento dell'y dentro il metodo drawString e verificando se sommare o sottrarre con in semplice if.
Finalmente son roiscito a far funzionare il programma e se ci sono riuscito, e sicuramente molto anche merito tuo! Grazie!
Per scrupolo potresti provare anche con il sistema suggerito da PGI-bis: perchè se è corretto ti consente di eliminare un if dal codice del metodo drawString, e non sarebbe male :)
drinkredbull
10-04-2009, 08:20
Per scrupolo potresti provare anche con il sistema suggerito da PGI-bis: perchè se è corretto ti consente di eliminare un if dal codice del metodo drawString, e non sarebbe male :)
Proverò a vedere quale dei 2 funziona meglio.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.