View Full Version : [java] seri problemi con applet
ciao,
ho dei seri problemi di performance con la mi applet.
l'applet è un menu a scorrimento e finchè lo provo dentro l'appletviewer (facendolo partire da eclipse) tutto ok, utilizzo cpu 1-3%, se lo metto dentro una pagina web e in locale lo faccio partire in firefox, ad esempio, la cpu sale al 30% costante anche senza fare nulla e dopo due animazioni si blocca tutto :mbe: :mbe: :mbe:
perchè mai dovrebbe succedere una cosa del genere?? :mc:
grazie
ma l'appletviewer non dovrebbe essere come un browser solo che ignora tutti i tag tranne <applet> ???
banryu79
17-11-2009, 12:39
Prova, se puoi e vuoi, a postare un po' di codice, magari il blocco più "computazionalmente intenso", così possiamo darci un occhio ;)
intanto grazie per la risposta, ok ci lavoro un attimo e posto ;)
ah dimenticavo, ci sono particali attenzioni da riporre sell0uso dei thread per le applet?
ok ho modificato un pò il codice per renderlo migliore, questo è il metodo paint che porta al flashing anche se uso il double buffering, questo metodo è dentra una classe che estende Canvas la quale è attaccata all'applet:
public synchronized void paint(Graphics g){
Graphics2D g2=(Graphics2D) bf.getDrawGraphics();
g2.setColor(Color.gray);
g2.fillRect(0, 0, panelWidth, panelHeight);
g2.setColor(Color.black);
boolean found=false;
for(int i=0; i<items.length; i++){
if(panelBound.intersects(items[i].getImageBound())){
if(items[i].getIndex()==selectedIndex){
//DISEGNO BORDO
final int bx=items[i].getBorderX();
final int by=items[i].getBorderY();
final int bw=items[i].getBorderWidth();
final int bh=items[i].getBorderHeight();
g2.drawImage(items[i].getBorder(), bx, by, bw, bh, this);
}
//DISEGNO IMMAGINE
final int ix=items[i].getImageX();
final int iy=items[i].getImageY();
final int iw=items[i].getImageWidth();
final int ih=items[i].getImageHeight();
g2.drawImage(items[i].getImage(), ix, iy, iw, ih, this);
found=true;
}
else{
if(found){
//HO GIA' TROVATO ELEMENTI ONSCREEN E QUESTO VIENE DOPO
//QUINDI ANCHE I SUCCESSIVI SONO DA SCARTARE
break;
}
}
}
//disegno delle frecce
g2.drawImage(leftArrow.getImage(), leftArrow.getX()-arrowMovement, leftArrow.getY(), leftArrow.getWidth(), leftArrow.getHeight(), this);
g2.drawImage(rightArrow.getImage(), rightArrow.getX()+arrowMovement, rightArrow.getY(), rightArrow.getWidth(), rightArrow.getHeight(), this);
//fine
g2.dispose();
bf.show();
}
non mi sembra nulla di speciale :confused:
perchè i flash?
EDIT: anche perchè anche un semplice rettangolo nero produce flash, quindi c'è qualcosa di sbagliato altrove mmmmm, è possibile che il fatto ci sia perchè aggiorno lo schermo ogni 10millisec?
banryu79
18-11-2009, 17:29
Perdonami, ma così non riesco a farmi un'idea della cosa nella sua interezza: se posti tutta la classe, non solo il metodo paint, forse riesco a capire meglio.
è un pò lunghetta :asd::
public class Desktop extends Canvas{
//COSTANTI
private final int ITEMS_PADDING=30;
private int ITEM_NUMBER;
//INTERNI DA CALCOLARE
private DesktopItem[] items;
private Rectangle2D panelBound;
private int selectedIndex;
private int centerX;
private int centerY;
private MiscItem leftArrow;
private MiscItem rightArrow;
private int arrowMovement;
private ArrowAnimation arrowAnimation;
private BufferStrategy bf;
//DA RICEVERE
private int panelWidth;
private int panelHeight;
//FLAG
private boolean isPerformingAnimation;
/**
* COSTRUTTORE
* @param descriptions
* @param itemURLs
* @param arrows
* @param imageDefaultURL
* @param borderURL
* @param panW
* @param panH
* @param itemNumber
*/
public Desktop(String[] descriptions, String[] itemURLs, String[] arrows, String imageDefaultURL, String borderURL, int panW, int panH, int itemNumber){
ITEM_NUMBER=itemNumber;
panelWidth=panW;
panelHeight=panH;
items=new DesktopItem[ITEM_NUMBER];
centerX=panelWidth/2;
centerY=panelHeight/2;
panelBound=new Rectangle2D.Double(0, 0, panelWidth, panelHeight);
isPerformingAnimation=false;
selectedIndex=0;
final int arrowSize=(int) (panelHeight*0.1);
final int arrowY=panelHeight-arrowSize;
final int arrowLeftX=0;
final int arrowRightX=panelWidth-arrowSize;
leftArrow=new MiscItem(arrowLeftX, arrowY, arrowSize, arrowSize);
rightArrow=new MiscItem(arrowRightX, arrowY, arrowSize, arrowSize);
arrowMovement=0;//
arrowAnimation=new ArrowAnimation(10, this);
//CARICAMENTO IMMAGINI
Image defaultImage=null;
Image border=null;
try {
defaultImage=new ImageIcon(new URL(imageDefaultURL)).getImage();
border=new ImageIcon(new URL(borderURL)).getImage();
leftArrow.setImage(new ImageIcon(new URL(arrows[0])).getImage());
rightArrow.setImage(new ImageIcon(new URL(arrows[1])).getImage());
} catch (MalformedURLException e1) {
e1.printStackTrace();
return;
}
final int defaulImageWidth= (int) (defaultImage.getWidth(this));
final int defaulImageHeight=(int) (defaultImage.getHeight(this));
int itemX=panelWidth/2;
for(int i=0; i<ITEM_NUMBER; i++){
items[i]=new DesktopItem(defaultImage, border, centerX, centerY, descriptions[i], defaulImageWidth, defaulImageHeight, panelWidth, panelHeight, i);
items[i].setCenterY(panelHeight/2);
items[i].setCenterX(itemX);
items[i].calculateImagePropieties();
itemX+=defaulImageWidth+ITEMS_PADDING;
}
}
/**
* FINISCE L'IMPOSTAZIONE
*/
public void performConfig(){
this.createBufferStrategy(2);
this.addMouseListener(new EventHandler());
arrowAnimation.start();
bf=this.getBufferStrategy();
}
/**
* AGGIORNA I VALORI DELLA POSIZIONE, GRANDEZA, ETC.. DI OGNI ELEMENTO
*/
public void updateItemsProprieties(){
for(int i=0; i<items.length; i++){
items[i].calculateImagePropieties();
if(selectedIndex==i)
items[i].calculateBorderProprieties();
}
}
/**
* EFFETTUA IL RENDERING CON UN BACKBUFFER DEGLI ELEMENTI A SCHERMO
*/
public void renderOnscreenItems(){
Graphics2D g2=(Graphics2D) bf.getDrawGraphics();
g2.setColor(Color.gray);
g2.fillRect(0, 0, panelWidth, panelHeight);
g2.setColor(Color.black);
boolean found=false;
for(int i=0; i<items.length; i++){
if(panelBound.intersects(items[i].getImageBound())){
if(items[i].getIndex()==selectedIndex){
//DISEGNO BORDO
final int bx=items[i].getBorderX();
final int by=items[i].getBorderY();
final int bw=items[i].getBorderWidth();
final int bh=items[i].getBorderHeight();
g2.drawImage(items[i].getBorder(), bx, by, bw, bh, this);
}
//DISEGNO IMMAGINE
final int ix=items[i].getImageX();
final int iy=items[i].getImageY();
final int iw=items[i].getImageWidth();
final int ih=items[i].getImageHeight();
g2.drawImage(items[i].getImage(), ix, iy, iw, ih, this);
found=true;
}
else{
if(found){
//HO GIA' TROVATO ELEMENTI ONSCREEN E QUESTO VIENE DOPO
//QUINDI ANCHE I SUCCESSIVI SONO DA SCARTARE
break;
}
}
}
//disegno delle frecce
g2.drawImage(leftArrow.getImage(), leftArrow.getX()-arrowMovement, leftArrow.getY(), leftArrow.getWidth(), leftArrow.getHeight(), this);
g2.drawImage(rightArrow.getImage(), rightArrow.getX()+arrowMovement, rightArrow.getY(), rightArrow.getWidth(), rightArrow.getHeight(), this);
//fine
g2.dispose();
bf.show();
//this.repaint();
}
/**
* IN CASO QUALCOSA ANDASSE STRORTO NEL THREAD CHE AGGIORNA GLI ELEMENTI RICARICA IL BACKUP
* @param oldItems
*/
public void restoreDesktopItems(DesktopItem[] oldItems){
items=oldItems;
}
/**
* PER IL THREAD DEL MOVIMENTO DELLE FRECCE AGGIORNA LA VARIABILE DA SOMMARE ALLA POSIZIONE
* @param movement
*/
public void setArrowMovement(int movement){
arrowMovement=movement;
renderOnscreenItems();
}
/**
* ESEGUE UNA NUOVA ANIMAZIONE E IMPOSTA LO STATO DI ESECUZIONE ANIMAZIONE
* @param index
* @param direction
* @param distance
*/
private void performAnimation(int index, int direction, int distance){
isPerformingAnimation(true);
new TranslationAnimation(items, direction, distance, this).start();
}
/**
* RITORNA LO STATO DI ANIMAZIONE
* @param flag
*/
public void isPerformingAnimation(boolean flag){
isPerformingAnimation=flag;
}
/**
* METODO CHIAMATO AUTONOMAMENTE DALLA VM
*/
public void paint(Graphics g){
renderOnscreenItems();
}
/**
* CLASSE INTERNA PER LA GESTIONE DEGLI EVENTI DEL MOUSE
* @author Andrea
*
*/
class EventHandler extends MouseAdapter{
public void mouseClicked(MouseEvent e){
if(!isPerformingAnimation){
final int x=e.getX();
final int y=e.getY();
if(leftArrow.getBound().contains(x, y)){
//CLICCATO FRECCIA SINISTRA
if(selectedIndex<=0)
return;
selectedIndex--;
final int absDist=Math.abs(centerX-items[selectedIndex].getCenterX());
int incr=absDist/100;
if(incr==0)
incr=1;
performAnimation(selectedIndex, +incr, absDist);
return;
}
if(rightArrow.getBound().contains(x, y)){
//CLICCATO FRECCIA DESTRA
if(selectedIndex>=ITEM_NUMBER-1)
return;
selectedIndex++;
final int absDist=Math.abs(centerX-items[selectedIndex].getCenterX());
int incr=absDist/100;
if(incr==0)
incr=1;
performAnimation(selectedIndex, -incr, absDist);
return;
}
boolean found=false;
for(int i=0; i<items.length; i++){
final Rectangle2D tempRect=items[i].getImageBound();
if(panelBound.intersects(items[i].getImageBound())){
if(tempRect.contains(x, y)){
//CLICCATA FIGURA A SCHERMO
selectedIndex=items[i].getIndex();
final int distance=centerX-items[i].getCenterX();
if(distance>0){
//MOVIMENTO VERSO DESTRA
final int absDist=Math.abs(distance);
int incr=absDist/100;
if(incr==0)
incr=1;
performAnimation(items[i].getIndex(), +incr, absDist);
return;
}
else{
if(distance<0){
//MOVIMENTO VERSO SINISTRA
final int absDist=Math.abs(distance);
int incr=absDist/100;
if(incr==0)
incr=1;
performAnimation(items[i].getIndex(), -incr, Math.abs(distance));
return;
}
else{
//HA CLICCATO L'IMMAGINE GIA' IN CENTRO
}
}
}
found=true;
}
else{
if(found){
//HO GIA' TROVATO ELEMENTI ONSCREEN E QUESTO VIENE DOPO
//QUINDI ANCHE I SUCCESSIVI SONO DA SCARTARE
break;
}
}
}
}
}
}
}
il filo logico è:
applet.init()->crea desktop e si inizializza il tutto
l'utente clicca sulle parti sensibili a schermo-> lancia un nuovo thread animazione che ogni millisecondo aggiorna le posizioni degli elementi e ridisegna
all'inizio parte un thread che gestisce il movimento delle frecce poste in basso a destra e sinistra per farle muovere e chiama ogni 10 millise il render.
questo è tutto :) e a questo punto inizio a pensare che ci sia qualcosa che non va nell'organizzazione più che codice :muro:
strutturato così non flesha più ma ogni tanto (sembra casualmente) qualche variabile è nulla e viene lanciata una nullpointerexception, e le prestazioni nel browser sono pessime occupando un intero core durante l'animazione :mbe:
Stai usando un BufferStrategy all'interno di un paint? Se sì, potrebbe essere la fonte del problema perchè il contesto grafico di un'applet è diverso dal contesto grafico di un'applicazione desktop. E' possibile che il browser non digerisca bene quella zuppa di buffer (per la precisione il fatto che il ciclo di aggiornamento del buffer usato da BufferStrategy si mescoli al ciclo di aggiornamento del buffer usato dal rootpane del tuo contenitore).
E' strano anche che paint sia sincronizzato perchè tutto il meccanismo di aggiornamento grafico AWT/Swing è a thread singolo e di solito si preferiscono strategie multi thread ottimistiche o single thread di tipo produttore-consumatore proprio per non intasare un metodo che tentativamente è invocato migliaia di volte al secondo.
Sotto il profilo delle performance considera anche il formato delle tue immagini che dovrebbero essere in modo che siano il più possibile compatibili con il contesto grafico dell'applet.
Stai usando un BufferStrategy all'interno di un paint? Se sì, potrebbe essere la fonte del problema perchè il contesto grafico di un'applet è diverso dal contesto grafico di un'applicazione desktop. E' possibile che il browser non digerisca bene quella zuppa di buffer (per la precisione il fatto che il ciclo di aggiornamento del buffer usato da BufferStrategy si mescoli al ciclo di aggiornamento del buffer usato dal rootpane del tuo contenitore).
E' strano anche che paint sia sincronizzato perchè tutto il meccanismo di aggiornamento grafico AWT/Swing è a thread singolo e di solito si preferiscono strategie multi thread ottimistiche o single thread di tipo produttore-consumatore proprio per non intasare un metodo che tentativamente è invocato migliaia di volte al secondo.
si il codice nuovo lo sistema, in effetti avevo fatto una cazzata..
Sotto il profilo delle performance considera anche il formato delle tue immagini che dovrebbero essere in modo che siano il più possibile compatibili con il contesto grafico dell'applet.
come faccio a fare questa verifica?
le mie immagini sono dei png 200x300 e le frecce 100x100, troppo? :confused:
EDIT:
il risultato è simile a questo http://www.javafx.com/samples/DisplayShelfMobile/index.html solo con più immagini per visibili e due frecce in basso che mi spostano il tutto di una posizione a dx o sx
Il codice è uguale al precedente, solo che anzichè essere direttamente incluso nel paint l'uso del buffer è invocato nel paint tramite un metodo di appoggio.
BufferStrategy non serve per avere un doppio buffer ma per dichiarare un sistema di rendering autonomo da quello standard.
Hai un tuo ciclo di aggiornamento grafico che periodicamente esegue le operazioni che adesso fai in renderOnScreenItem senza passare da paint, paintComponent o altro.
La questione delle immagini non sta nelle dimensioni ma nel formato. Ad esempio se carichi una PNG da file probabilmente il suo formato sarà un ARGB a 8 bit per canale. Il buffer video ha normalmente un formato più efficiente in termini di spazio. Quando la pipeline di rendering Java2D va a disegnare questa immagini sul buffer deve convertire il formato ARGB della sorgente nel formato che hanno i pixel nel buffer video.
Per ottenere un'immagine che non richieda questa conversione devi interrogare il contesto grafico del display in uso e chiedere la creazione di un'immagine vuota avente il formato più idoneo alla proiezione sullo schermo (cioè quello che non richiede trasformazioni).
IL contesto grafico lo ottieni invocando il metodo "getGraphicsConfiguration" di un qualsiasi componente AWT/Swing. C'è un piccolo problema di tempistica che deriva dal fatto che un componente restituisce un valore diverso da null per un'invocazione di getGraphicsConfiguration solo dopo che lo stesso componente è stato proiettato sullo schermo (altrimenti non sarebbe in grado di "sapere" in che contesto grafico si trova).
L'applicazione quindi dovrebbe partire, proiettarsi sullo schermo di destinazione, convertire le immagini, con una cosa tipo:
GraphicsConfiguration gc = componente.getGraphicsConfiguration();
//per ogni immagine X
BufferedImage image = gc.createCompatibleImage(width, height, X.getTransparency());
Graphics g = image.getGraphics();
g.drawImage(X, 0, 0, null);
X = null;
X = image;
e quindi avviarsi in senso proprio. In questo caso "image" ha un formato compatibile con il buffer video e i pixel di "X", l'originale, vengono convertiti dall'esecuzione di drawImage, un po' come farebbe la pipeline Java2D solo che qui lo facciamo una volta sola per tutte.
Con questo ottieni un miglioramente delle performace di rendering ma non è certamente qui il grosso dei problemi che riscontri, anche perchè usi immagini relativamente piccole. Punterei decisamente il dito sulla gestione di quel BufferStrategy.
Tieni conto che se al posto di Applet usi JApplet ottieni un doppio buffer automatico. In questo caso ti limiteresti a definire le tue operazioni di disegno nel paintComponet di un qualche contenitore senza usare BufferStrategy.
innanzi tutto grazie della risposta.
ho provato a fare ciò che dici per le immagini, è un'ottima idea ma ahimè non cambia nulla...
quindi la questione pensi stia nel bufferstrategy e non nelle volte che renderizzo(intendo come numero, anche se mi sembra piuttosto strano....)?
io uso una japplet ma non capisco, ovunque dicono che i componenti swing hanno in double buffer for free, ma io non lo vedo :mbe:, o forse sbaglio io ogni volta a impostare il programma, ti sembra una scaletta per lo meno "decente" quella che ho descritto qualche post fa per l'obbiettivo che voglio ottenere?
anche perchè è la prima volta che mi cimento in applicazioni che includono animazioni automatizzate :rolleyes:
grazie
Usi una JApplet ma mettendoci dentro un canvas il doppio buffer di swing viene incenerito.
Il buffer di Swing non lo vedi ma c'è (ed è peraltro un BufferStrategy). Lo usi automaticamente per tutte le operazioni di disegno che metti in un paintComponent.
public class Desktop extends JComponent {
@Override
protected void paintComponent(Graphics g) {
//g è la superficie corrente di un BufferStrategy che "c'è ma non si vede"
//a gestirlo ci pensa swing.
}
}
Per quanto riguarda l'animazione il tuo approccio non è concettualmente errato. puoi tranquillamente affidare l'animazione ad un thread parallelo all'Event Dispatcher AWT (quello che esegue i vari paintXYZ e cattura e distribuisce gli eventi) come mi sembra che tu faccia con TranslationAnimation.
Non vedo problemi di sincronizzazione a parte eventuali scritture che i Thread TranslationAnimation possono fare sul campo "items" e, indirettamente, tramite "this". Si tratta comunque di problemi che non si manifestano con il blocco del programma (semmai avrai un'animazione inconsistente).
Elimina BufferStrategy, estendi JComponent anzichè Canvas, quello che fai in renderOnscreenItems fallo nel metodo paintComponent(Graphics) usando il graphics che questo metodo ha come parametro al posto del graphics che otterresti da BufferStrategy.
Dopodichè anzichè invocare renderOnscreenItems invochi repaint().
grazie mille!
in questo modo ho eliminato il flashing ed è già una gran cosa, rimane il problema delle prestazione, perchè in applet viewer la cpu sta al 7% di picco, mentre in firefox e altri raggiunge anche il 40% :sob:
consigli?
PS: ho visto i filmati che hai in firma, mamma mia se hai fatto tu( o fai parte d i quel team) quel programma li sei veramente un grande, porca miseria complimenti :D
Un degrado così marcato indica che da qualche parte c'è qualcosa che fai ma non dovresti. Il problema è capire cosa.
Prova a lanciare l'applet nel browser, poi apri una console dei comandi, digiti:
jvisualvm
e premi invio.
Nella finestra che si apre, sulla destra, dovresti trovare una voce tipo "sunplugin2.qualcosa.quacos'altro PID blabla". Doppio click su quella. Il programma inizierà a monitorare l'attività dell'applet.
Vai nella scheda "profiler" e premi il pulsante "CPU". Dopo un po' di macinamenti vari dovrebbe apparire un elenco di metodi, ordinati per carico di lavoro.
Dai un'occhiata ai nomi dei metodi e controlla se per caso non ci sia un metodo particolare di una classe da te definita tra quelli in cima alla lista. Normalmente i metodi in testa sono tutti relativi al codice di basso livello che gestisce la pipeline java2d e tra questi e gli altri c'è un abisso in termini di tempo di esecuzione (in pratica i metodi da te definiti dovrebbero risultare scarsamente rilevanti per il tempo di esecuzione totale).
Se un tuo metodo occupa la CPU per un tempo rilevante in rapporto al tempo richiesto dai metodi della pipeline java 2d allora quel metodo è un buon candidato ad una verifica.
Un degrado così marcato indica che da qualche parte c'è qualcosa che fai ma non dovresti. Il problema è capire cosa.
Prova a lanciare l'applet nel browser, poi apri una console dei comandi, digiti:
jvisualvm
e premi invio.
Nella finestra che si apre, sulla destra, dovresti trovare una voce tipo "sunplugin2.qualcosa.quacos'altro PID blabla". Doppio click su quella. Il programma inizierà a monitorare l'attività dell'applet.
Vai nella scheda "profiler" e premi il pulsante "CPU". Dopo un po' di macinamenti vari dovrebbe apparire un elenco di metodi, ordinati per carico di lavoro.
Dai un'occhiata ai nomi dei metodi e controlla se per caso non ci sia un metodo particolare di una classe da te definita tra quelli in cima alla lista. Normalmente i metodi in testa sono tutti relativi al codice di basso livello che gestisce la pipeline java2d e tra questi e gli altri c'è un abisso in termini di tempo di esecuzione (in pratica i metodi da te definiti dovrebbero risultare scarsamente rilevanti per il tempo di esecuzione totale).
Se un tuo metodo occupa la CPU per un tempo rilevante in rapporto al tempo richiesto dai metodi della pipeline java 2d allora quel metodo è un buon candidato ad una verifica.
ancora grazie mille, ho individuato il problema :D
public class TranslationAnimation extends Thread {
private final int INCREMENT_ADDED=15;
private DesktopItem[] items;
private DesktopItem[] backupItems;
private int increment;
private int distance;
private Desktop launcher;
private int currentAlpha;
//FLAG
private boolean done;
public TranslationAnimation(DesktopItem[] _items, int incr, int _distance, Desktop _launcher){
items=_items;
increment=(int) ((Math.signum(incr))*(Math.abs(increment)+INCREMENT_ADDED));;
distance=_distance;
launcher=_launcher;
backupItems=_items.clone();
done=false;
currentAlpha=0;
}
public void run(){
try{
final Color defColor=launcher.getItemDescriptionColor();
final int r=defColor.getRed();
final int g=defColor.getGreen();
final int b=defColor.getBlue();
launcher.setItemDescriptionColor(new Color(r, g, b, 0));
while(!done){
Thread.sleep(10);
Thread.yield();
if(distance-Math.abs(increment)<0){
//RIDUCO L'INCREMENTO PER FARLO POI COINCIDERE CON IL CENTRO ESATTO
increment=(int) (Math.signum(increment)*(1));
}
distance-=Math.abs(increment);
if(distance==0){
done=true;
}
for(int i=0; i<items.length; i++){
items[i].increaseCenterX(increment);
}
for(int i=0; i<items.length; i++){
items[i].calculateImagePropieties();
if(launcher.selectedIndex==i)
items[i].calculateBorderProprieties();
}
launcher.render();
}
//FINITO IL MOVIMENTO
//APPARIZIONE DELLA SCRITTA
done=false;
while(!done){
Thread.sleep(10);
Thread.yield();
currentAlpha+=5;
if(currentAlpha<0 || currentAlpha>200){
currentAlpha=255;
done=true;
}
launcher.setItemDescriptionColor(new Color(r, g, b, currentAlpha));
}
}
catch (Exception e) {
launcher.restoreDesktopItems(backupItems);
e.printStackTrace();
}
finally{
launcher.isPerformingAnimation(false);
}
}
}
in questo thread però rimane un problemino, in pratica sembra casualmente la cpu resta fissa al 25% senza eseguire animazioni e con la jvisualvm vedo che gran parte del carico è del suo metodo run :boh: però ho controllato con un System.out e il metodo run finisce correttamente e il 3d muore :doh:
è una cosa sporadica che non influisce più di tanto.
ho trovato invece dei problemi nel caricare immagini. in pratica il mio jar sta nel server e ha le immagini dentro una cartella "/Images/.../immagine.png" e per caricarla correttamente devo fare tutto questo giro:
defaultImage=new ImageIcon(getClass().getResource(imageDefaultURL)).getImage();
:mbe: cioè su internet nelle guide usano miaApplet.getDocumentBase ma a me non funziona, non è che potresti postare solo l'istruzione corretta per caricare le immagini in un'applet?
(so che non ce nè UNA corretta, ma quella più comunemente usata e affidabile)
grazie
Potrebbe essere il garbage collector che approfitta dello stato di "quiete" del tuo programma per fare un po' di pulizia. Puoi verficarlo sempre tramite jvisualvm nella scheda "monitor": dovresti notare un picco nell'attività del GC a cui corrisponde un picco nell'uso della CPU.
Il modo in cui carichi le immagini è quello giusto: quando un programma ha necessità di caricare risorse la cui posizione dipende dal percorso del programma, getResource è il modo giusto per farlo.
Funziona anche getDocumentBase con l'unico problema che il valore di getDocumentBase è diverso da null solo dopo che l'applet è stata avviata. Così capita ad esempio che se lo usi in un inizializzatore getDocumentBase ti spara un bel "null" e resti in braghe di fustagno.
Idem per getCodeBase.
il getResource di ClassLoader a cui accedi tramite getClass().getResource è invece vivo e vegeto ancor prima che venga letta la prima classe del tuo programma.
Potrebbe essere il garbage collector che approfitta dello stato di "quiete" del tuo programma per fare un po' di pulizia. Puoi verficarlo sempre tramite jvisualvm nella scheda "monitor": dovresti notare un picco nell'attività del GC a cui corrisponde un picco nell'uso della CPU.
Il modo in cui carichi le immagini è quello giusto: quando un programma ha necessità di caricare risorse la cui posizione dipende dal percorso del programma, getResource è il modo giusto per farlo.
Funziona anche getDocumentBase con l'unico problema che il valore di getDocumentBase è diverso da null solo dopo che l'applet è stata avviata. Così capita ad esempio che se lo usi in un inizializzatore getDocumentBase ti spara un bel "null" e resti in braghe di fustagno.
Idem per getCodeBase.
il getResource di ClassLoader a cui accedi tramite getClass().getResource è invece vivo e vegeto ancor prima che venga letta la prima classe del tuo programma.
grazie mille per le spiegazioni.:yeah:
La mia situazione è questa:
"cartellasito"
index.html
miojar.jar
"cartellaImmagini"
miaImmagine.png
facendo:
URL url=getClass().getResources("/cartellaImmagini/miaImmagine.png");
la url vale null :mbe:
non vorrei che getResources() partisse a cercare il file da dove sta il .class cioè dentro al .jar, è così?:wtf:
qualche soluzione?
(ovviamente tutto il mio programma sta dentro il jar)
Le radici di getResource sono le radici del classpath. Le radici del classpath includono le radici di ogni jar o zip richiesti e variamente specificati per l'esecuzione del programma.
Tra le radici di un'applicazione desktop è inclusa la directory di lavoro (il ".").
Tra le radici di un applet è inclusa la cartella che contiene il documento html in cui è dichiarato il tag applet.
E' strano quindi che getResource risponda picche alla tua richiesta perchè rispetto alla struttura di directory che indichi il percorso usato appare corretto.
Prova ad aprire questa pagina:
test2.html (http://www.tukano.it/test/test2/test.html)
C'è dentro quest'applet:
import javax.swing.*;
public class TestAppletClasspath extends JApplet {
public void init() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
add(new JLabel(String.valueOf(getClass().getResource("/res/test.txt"))));
}
});
}
}
Se compare un testo diverso da null nel quadrato grigio dell'applet c'è qualcosa che non va nel tuo codice. Se compare null c'è qualcosa che non va nel tuo classpath.
grazie mille per la disponibilità!!
mi leggerò i pdf che hai messo sul sito ;)
ora il grosso del lavoro è ok, diciamo che non è ottimizzato, ma non era quello lo scopo (purtroppo)
se hai tempo dacci un'occhiata: http://andre90.altervista.org/ e tutti i consigli e/o critiche sono ben accetti :asd:
fammi sapere!!
Mi sembra che funzioni bene.
Se disegni del testo abilita l'antialiasing del font, altrimenti sembra sempre un po' seghettato.
Per farlo, dato un oggetto Graphics g:
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
dopodichè i vari drawString o draw di TextLayout eccetera applicati a g2d avranno l'antialias.
giusta osservazione ho corretto :D
ora l'ho messo anche al bordo della shelf dove ci sono le freccie che era arrotondata=seghettata..
grazie mille per la disponibilità!:cincin:
sto cercando di risolvere quel sovraccarico, che mi porta la cpu a un 25% costante senza fare apparentemente nulla, posto l'immagine di jvisualvm,
http://img19.imageshack.us/img19/9782/problemapplet.th.jpg (http://img19.imageshack.us/i/problemapplet.jpg/)
dove dice che la maggior parte del tempo dedicato dalla cpu lo utilizza javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run()
e credo che sia normale, ma c'è sempre una percentuale che viene utilizzata da TranslationAnimation.run() che dovrebbe invece essere bello che morto :wtf:
riposto il codice di TranslationAnimation:
public class TranslationAnimation extends Thread {
private final int INCREMENT_ADDED=15;
private DesktopItem[] items;
private DesktopItem[] backupItems;
private int increment;
private int distance;
private Desktop launcher;
private int currentAlpha;
//FLAG
private boolean done;
public TranslationAnimation(DesktopItem[] _items, int incr, int _distance, Desktop _launcher){
items=_items;
increment=(int) ((Math.signum(incr))*(Math.abs(increment)+INCREMENT_ADDED));;
distance=_distance;
launcher=_launcher;
backupItems=_items.clone();
done=false;
currentAlpha=0;
}
public void run(){
try{
final Color defColor=launcher.getItemDescriptionColor();
final int r=defColor.getRed();
final int g=defColor.getGreen();
final int b=defColor.getBlue();
launcher.setItemDescriptionColor(new Color(r, g, b, 0));
while(!done){
Thread.sleep(10);
Thread.yield();
if(distance-Math.abs(increment)<0){
//RIDUCO L'INCREMENTO PER FARLO POI COINCIDERE CON IL CENTRO ESATTO
increment=(int) (Math.signum(increment)*(1));
}
distance-=Math.abs(increment);
if(distance==0){
done=true;
}
for(int i=0; i<items.length; i++){
items[i].increaseCenterX(increment);
}
for(int i=0; i<items.length; i++){
items[i].calculateImagePropieties();
if(launcher.selectedIndex==i)
items[i].calculateBorderProprieties();
}
if(!launcher.isRendering())
launcher.render();
}
//FINITO IL MOVIMENTO
//APPARIZIONE DELLA SCRITTA
done=false;
while(!done){
Thread.sleep(10);
Thread.yield();
currentAlpha+=5;
if(currentAlpha<0 || currentAlpha>200){
currentAlpha=255;
done=true;
}
launcher.setItemDescriptionColor(new Color(r, g, b, currentAlpha));
if(!launcher.isRendering())
launcher.render();
}
}
catch (Exception e) {
launcher.restoreDesktopItems(backupItems);
e.printStackTrace();
}
finally{
launcher.isPerformingAnimation(false);
}
}
}
e il modo in cui lo chiamo:
private void performAnimation(int index, int direction, int distance){
isPerformingAnimation(true);
new TranslationAnimation(items, direction, distance, this).start();
}
a me sembra essere tutto ok, non vedo il motivo per cui il suo metodo run quando è finita l'operazione di movimento dovrebbe occupare ancora cpu :wtf:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.