PDA

View Full Version : [JAVA] aiuto sulle JLabel


alessia86
26-08-2009, 20:25
Ciaoooo a tutti...vorrei sapere se creo una label con un tipo int..ad es:


int punteggio=0;

Label lab=new Label(" "+punteggio);




se voglio che punteggio ad es sia visualizzata in grassetto,carattere 30..Come faccio visto che punteggio è di tipo int?
Vi ringrazio!!!

isAlreadyInUse
26-08-2009, 20:29
setFont(new Font("sansserif",Font.BOLD,12);

PGI-Bis
26-08-2009, 20:33
Puoi cambiare il font dell'etichetta:

lab.setFont(lab.getFont().deriveFont(Font.BOLD));

Se invece vuoi scrivere una parte del testo in grassetto puoi usare html:

JLabel lab = new JLabel("<html>Punteggio: <b>" + String.valueOf(punteggio) +"</b></html>");

alessia86
29-08-2009, 09:52
Grazie mille..Il testo sono riuscita a modificarlo..Ora però è sorto un altro problema..Allora la JLabel l'ho messa in un JPanel e fin qui tutto ok..Ora,qst label mi visualizza il punteggio del videogioco..e quindi si aggiorna di continuo..

Il problema è che le dim della label sono piccole e di conseguenza qnd il punteggio arriva a mille non si visualizza tutto..

Ho provato anche a stampare la larghezza della label e mi da uguale a zero...

Qualcuno sa aiutarmi??

Grazie

PGI-Bis
29-08-2009, 11:40
le dimensioni dell'etichetta dipendono sia dal contenuto sia dal layout del contenitore in cui l'etichetta si trova. Ad esempio se hai una singola JLabel inserita in un JPanel il cui LayoutManager è un FlowLayout orizzontale e il pannello è a sua volta inserito in un contenitore che gli attribuisce una larghezza sufficientemente ampia allora la larghezza dell'etichetta varierà conformemente al suo contenuto. Nell'esempio che segue la cosa si nota per effetto dell'espansione del bordo assegnato all'etichetta:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.concurrent.atomic.*;

public class Main {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
start();
}
});
}

private static void start() {
final AtomicInteger value = new AtomicInteger(0);
final JLabel label = new JLabel("Punteggio " + value.get());
label.setBorder(BorderFactory.createEtchedBorder());
ActionListener task = new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setText("Punteggio: " + value.addAndGet(100));
}
};
final javax.swing.Timer updater = new javax.swing.Timer(250, task);
JPanel container = new JPanel(new FlowLayout(FlowLayout.LEFT));
container.add(label);
container.setPreferredSize(new Dimension(400, 400));
JFrame window = new JFrame("Test");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(container);
window.pack();
window.setVisible(true);
updater.start();
}
}

La larghezza dell'etichetta e di un qualsiasi altro componente AWT/Swing è zero finchè quel componente non sia inserito in un contenitore di primo livello visualizzabile. In pratica finchè non è sullo schermo getWidth() e getHeight() danno sempre zero.

Puoi imporre al componente una certa dimensione usando setPreferredSize MA il rispetto della dimensione che assegni è condizionato al tipo di Layout e allo spazio effettivamente disponibile.

alessia86
29-08-2009, 12:46
Grazie per la spiegazione..Ma la label che ho creato l'ho aggiunta ad un jpanel che a sua volta è in un altro pannello e che si trova in un frame..
Forse è qst che non va?

PGI-Bis
29-08-2009, 12:53
Il principio è lo stesso a prescindere dall'annidamento, cioè da quanti pannelli si trovino tra il componente e la finestra.

Diventa "solo" più complicato stabilire una spaziatura dinamica.

Una prova che puoi fare è quella di dare all'etichetta una dimensione idealmente sufficiente a contenere tutti i possibili output.

Prova a dire:

miaEtichetta.setPreferredSize(300, 40);

Così facendo imponi all'etichetta una dimensione preferita di 300 punti in larghezza e 40 in altezza. Il rispetto di questa imposizione dipende dai layout (ad esempio se l'etichetta si trova in un GridLayout è efficace quanto dire magicabula ma se si trova in un FlowLayout l'etichetta riceverà effettivamente quei 300x40 punti)

alessia86
29-08-2009, 13:14
Se metto setPreferredSize mi da errore..Allora ti scrivo il codice:


Label lab=new Label(" "+Punteggio,Label.CENTER);


lab.setFont(new Font("sansserif",Font.BOLD,30));

lab.setForeground(Color.red);

JPanel panel=new JPanel();

panel.setBackground(Color.black);

panel.add(lab,BorderLayout.SOUTH);

this.add(panel,BorderLayout.SOUTH);

this.pack();
this.setVisible(true);

//qst codice appena scritto è contenuto in un JFrame...poi ogni volta che mi devo aggiornare il punteggio richiamo il seguente metodo(anch'esso contenuto nella classe JFrame):


public void aggiornaPunteggio(){

if(mangiato)
Punteggio+=150;
else

Punteggio+=100;



lab.setText(" "+Punteggio);

}

PGI-Bis
29-08-2009, 13:23
setPreferredSize è un metodo di Component, ce l'ha pure (J)Label. Non dovrebbe darti errore. Nota che l'argomento di setPreferredSize è un Dimension: setPreferredSize(new Dimension(w, h)).

Prova con:

lab.setPreferredSize(new Dimension(300, 40));

alessia86
29-08-2009, 14:19
ok..cosi' la label mi da..perfetto!! Grazie davv tanto per l'aiuto che mi stai dando..Il pannello che visualizza la label si sovrappone all'immagine che ho messo affianco..ed il pannello non me lo fa spostare un pò più in la..Ho provato a fare:
panel.setLocation(350,560);

Anche con la label ma non si sposta :mc:

PGI-Bis
29-08-2009, 14:24
Il posizionamento assoluto (con setLocation) non funziona perchè il LayoutManager lo sovrascrive.

Se usi effettivamente Label nel tuo progetto - e non è un semplice refuso nel post - rimpiazzalo con JLabel.

E' possibile infatti che la sovrapposizione che vedi sia dovuta al mix AWT/Swing (Label è un componente AWT, JLabel è la controparte Swing).

Fai una prova e vedi se risolve.

alessia86
29-08-2009, 14:33
Cosa molto strana e che non capisco è che se metto JLabel non mi visualizza proprio niente..Nemmeno l'intero frame dove ho inserito le altre cose

PGI-Bis
29-08-2009, 15:10
In effetti è piuttosto strano.

E' possibile che la cosa sia dovuta all'inserimento della JLabel in una posizione tale da sostituire il precedente contenuto della finestra. Ad esempio se io scrivessi:

JFrame x = new JFrame();
x.add(un bel pannello pieno di cose, BorderLayout.CENTER);

x.add(un'etichetta);

nella mia finestra vedrei solo l'etichetta perchè il LayoutManager BorderLayout stabilisce che quando due componenti sono inseriti nella stessa posizione l'ultimo inserito sostituisce il precedente.

Senza il codice completo è difficile poter dire di più.

alessia86
30-08-2009, 09:06
Ti scrivo il codice perchè ho capito quello che vuoi dire...però non so proprio come risolvere il problema.. :muro:




//NELLA CLASSE FRAME HO LA SEGUENTE ETICHETTA:

lab=new Label(" "+Punteggio,Label.CENTER);

lab.setFont(new Font("sansserif",Font.BOLD,30));

lab.setPreferredSize(new Dimension(150, 50));

lab.setForeground(Color.red);


score=kit.getImage("Immagini/score.gif");

//score è l'immagine che viene sovrapposta dalla label

panel=new JPanel();
panel.setBackground(Color.black);
panel.add(lab,BorderLayout.SOUTH);
this.add(panel,BorderLayout.SOUTH);

this.pack();
this.setVisible(true);

kit.getDefaultToolkit().sync();





//L'IMMAGINE SCORE VIENE DISEGNATA DALLA CLASSE RENDER


public void render()
{

bs=getBufferStrategy();
g=bs.getDrawGraphics();

g.drawImage(score, 250, 560, this);

bs.show();


}

PGI-Bis
30-08-2009, 14:38
Quella porzione di codice è corretta. Il BufferStrategy che usi nel metodo render è di un Canvas che si trova al centro della finestra?

alessia86
30-08-2009, 15:20
non so se vuol dire al centro..Ti mando il codice dove faccio partire qst frame:



public Gioco(GraphicsDevice device,Frame F)
{


DisplayMode d=new DisplayMode(800,600,32,0);





Fr=new FrameG(d,F,device);


Fr.createBufferStrategy(2);

device.setFullScreenWindow(Fr);




try {
if(device.isDisplayChangeSupported())
device.setDisplayMode(d);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}



}
}

PGI-Bis
30-08-2009, 15:36
MMhhhh... la trama si complica :what:

La finestra che va in fullscreen e sulla quale disegni usando il BufferStrategy è anche la stessa a cui aggiungi i componenti?

Se sì non funziona come ti aspetti.

BufferStrategy e il "normale" rendering dei componenti sono mutualmente esclusivi.

Puoi ottenere varie bizzarrie perchè hai il tuo ciclo di redering sulla superficie della finestra frapposto alle operazioni di disegno che il framework cerca di fare sulla stessa superficie: quando disegni col bufferstrategy cancelli tutto quello che stava cercando di fare AWT/Swing, quando AWT/Swing disegnano cancellano tutto quello che stavi cercando di fare tu. Se in mezzo ci sono dei componenti trasparenti la cosa diventa anche più strana perchè parte della superficie viene rigenerata e parte no.

Se vuoi fare un mix di BufferStrategy e componenti devi usare un Canvas per la parte di interfaccia che usa BufferStrategy e una normale catena di componenti AWT per la parte a componenti (puoi anche usare componenti Swing purchè non siano in tutto o in parte sovrapposti al canvas).

Altrimenti puoi rinunciare ai componenti e usare solo BufferStrategy. In questo caso per disegnare, ad esempio, il punteggio, dirai nel tuo ciclo di rendering:

g.drawString("Punteggio: " + punteggio, x, y);

Puoi anche usare un componente come Label come renderer:

g.translate(x,y);
label.print(g);
g.translate(-x,-y);

alessia86
30-08-2009, 15:41
Si..è la stessa..in pratica in quella finestra c'è il videogioco...e poi sempre u di essa ho disegnato diciamo le "vite" del personaggio del videogioco..ed avevo aggiunto la label ....Altrimenti come posso fare per ottenere sempre una finestra a schermo intero senza avere qst tipo di interferenze?

PGI-Bis
30-08-2009, 17:42
La finestra può andare in modalità schermo intero a prescindere dal suo contenuto. Per intenderci non è necessario usare un BufferStrategy sulla finestra per poter dire device.setFullscreenWindow(x).

Alla fine della fiera io eliminerei tutta la componentistica (etichette, pannelli, pulsanti eccetera) e andrei direttamente sul disegno nudo e crudo.

Ad esempio se vuoi disegnare il testo "Punteggio XYZ" usi un TextLayout al posto di una Label. Se dai in pasto a un TextLayout una stringa e un font quello ti dice quanto è grande il rettangolo necessario per disegnarla. A quel punto puoi disegnarla "in basso" semplicemente sottraendo all'altezza della tua finestra l'altezza del TextLayout.

Esempio rapido rapido:

import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;

public class Main {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
start();
}
});
}

private static final Font FONT_PUNTEGGIO = new Font("serif", Font.BOLD, 30);
private static int punti;

private static void start() {
final JFrame window = new JFrame("Test");
ActionListener painter = new ActionListener() {
public void actionPerformed(ActionEvent e) {
render(window);
}
};
final javax.swing.Timer timer = new javax.swing.Timer(1, painter);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.addWindowListener(new WindowAdapter() {
public void windowOpened(WindowEvent e) {
window.createBufferStrategy(2);
timer.start();//avvia il motore di gioco
}

public void windowClosing(WindowEvent e) {
timer.stop();//ferma il motore di gioco
}
});
window.setSize(640,480);
window.setVisible(true);
}

private static void render(JFrame window) {
BufferStrategy bs = window.getBufferStrategy();
Insets border = window.getInsets();
int width = window.getWidth() - border.left - border.right;
int height = window.getHeight() - border.top - border.bottom;
Graphics2D g = (Graphics2D)bs.getDrawGraphics();
g.translate(border.left, border.top);

g.setPaint(Color.BLACK); //disegna lo sfondo
g.fillRect(0,0,width,height);

String punteggio = "Punteggio: " + punti; //disegna il punteggio
TextLayout text = new TextLayout(punteggio, FONT_PUNTEGGIO, g.getFontRenderContext());
Rectangle2D area = text.getBounds();
double x = Math.min(width - area.getWidth(), 2 * width / 3);
double y = height - area.getHeight();
g.translate(x,y);
g.setPaint(Color.RED);
text.draw(g, 0, 0);
g.translate(-x,-y);

g.translate(border.left, border.top);

bs.show(); //proietta il buffer sullo schermo

punti++;
}
}

Tu il ciclo di rendering ce l'hai già, devi solo trasferire là dentro le operazioni di disegno che ora affidi ai componenti.