Buona sera,
Come aggiorno un pannello per evitare che gli oggetti vengano ricalcolati e quindi, le modifiche siano visibili solo alla fine del/dei ciclo/cicli?
Buona sera,
Come aggiorno un pannello per evitare che gli oggetti vengano ricalcolati e quindi, le modifiche siano visibili solo alla fine del/dei ciclo/cicli?
jabjoint
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Ciao @andbin, grazie per la risposta:
Ok mi spiego meglio, in effetti è vero.
Faccio dei cicli nella paintComponent ma ho due problemi:
1)
Carico un immagine da un file nel pannello.
Scrivo sopra l' immagine del pannello, fisicamente sul pannello.
Non riesco ad aggiornare la Graphics in paintComponent durante i due cicli for che rappresentano gli elementi disegnandoli sul pannello.
Le modifiche avvengono solo alla fine dei cicli.
Per esempio vorrei anche visualizzare in tempo reale una percentuale di progresso che segnala dopo quanto finirà il processo dei due for nella paintComponent.
2)
Quando aggiorno una combo-box mi si aggiorna la paintComponent.
Qui mi pare ci sia un metodo per evitare l'aggiornamento?
![]()
Ultima modifica di jabjoint; 11-10-2022 a 09:30
jabjoint
Purtroppo non è ancora molto chiaro .... magari riporta del codice che potrebbe chiarire.
Comunque visto che parli di paintComponent, se fai del custom painting in un componente (es. JPanel), allora in generale è bene dire che il paintComponent deve essere il più breve ed efficiente possibile. In sostanza, vuol dire che nel paintComponent:
- non devi fare I/O (né su file e meno ancora su networking)
- non devi (continuamente) caricare immagini
- non devi fare sleep o altre operazioni potenzialmente bloccanti
(eventualmente si può caricare immagini/icone non troppo grandi in modo "lazy" cioè solo al primo paintComponent e poi ri-usarle).
Poi bisogna anche vedere in quale componente stai ridefinendo il paintComponent. Se è un JPanel, esso usa per default il double-buffering. Vuol dire che 2 disegni in sequenza NON li "vedi" distintamente nemmeno se in mezzo ci mettessi (per ipotesi) uno sleep di 1 secondo.
Ma il double-buffering c'è per un motivo ben preciso, per evitare i brutti effetti di flickering.
Ultima modifica di andbin; 11-10-2022 a 12:03
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Ho tentato anche con JLabel, vorrei disegnare l'immagine su una Label e poi aggiornarla tramite setRGB(x,y,int_rgb);
Tuttavia non riesco a visualizzarla.
Provo con:
Dove lImg è la Jlabel settata come visibile ed aggiunta al JPanel.
Mentre img è istanza di Immagine a cui passo il file da leggere.codice:System.out.println(lImg.imageUpdate(img.getImage().getSubimage(0,0, 10, 10), ALLBITS, 0, 0, 10,10));
codice:class Immagine { private BufferedImage image; Immagine(File file){ try { image = ImageIO.read(file); } catch (IOException e) { e.printStackTrace(); } } BufferedImage getImage(){ return image; }
Ho tentato anche con:
Perché giustamente il primo metodo risultava false...nulla da farecodice:ImageIcon iconIMG = new ImageIcon(); iconIMG.setImage(img.getImage()); lImg = new JLabel(iconIMG);
Ultima modifica di jabjoint; 11-10-2022 a 22:10
jabjoint
Ciao andbin, ti posto il codice.
In parte "forse" ho migliorato con questo codice(senza overraidare paintComponent):
Il codice: inserito in una classe invocata da un bottone:
Tuttavia ancora non riesco ancora:codice:int progresso=0; file = new File(fileName); //fileName è il path. img = new Immagine(file); //Immagine è una classe che si occupa di disegnare iconIMG.setImage(img.getImage()); //limite progresso? Da aggiustare penso in realtà, sbaglia di poco! double limiteProgresso = (endX-begX+k)*(endY-begY+k)/(k*k); int RED=180; int GREEN=100; int BLUE=100; try { for(double x=begX; x<=endX; x+=k){ for(double y=begY; y<=endY; y+=k){ //Risolve le espressioni da un altro package: X0 = ValuteExpression.solveExp(eX,"x",x,"y", y); Y0 = ValuteExpression.solveExp(eY,"x",x,"y", y); Z0 = ValuteExpression.solveExp(eZ,"x",x,"y", y); //progresso? Da aggiustare penso in realtà, sbaglia di poco! double progress = (int)(2+100.0*progresso/limiteProgresso); //Qui dovrei aggiungere in tempo più o meno "reale" il progress dell' immagine ad un'altra label. RED = (int)(Math.random()*255); GREEN = (int)(Math.random()*255); BLUE = (int)(Math.random()*255); //Metodo che setta e disegna il punto di Immagine img.setPointXYZ(X0,Y0,Z0,new Color(RED,GREEN,BLUE)); img.disegna(scala); //invoca il metodo disegna della classe Immagine. //Aggiorna l'etichetta lImg, definita/dichiarata in classe Pannello che estende JPanel. lImg.imageUpdate(img.getImage(),ALLBITS,0,0,500,500); } } } catch(Exception ex) { System.out.println("Errore nella gestione delle espressioni"); }
- a non ricaricare l'immagine tutte le volte quanto premo il bottone, vorrei si pulisse(pensavo a flush() ma non va...)
- a mostrare il progress in un etichetta in tempo più o meno reale.
- a mostrare l'update dell'immagine in tempo reale???
Ultima modifica di jabjoint; 12-10-2022 a 10:23
jabjoint
La cosa più semplice in linea generale sarebbe:
a) crea il BufferedImage
b) prendi il Graphics2D, disegna quanto vuoi, poi dispose() del Graphics2D
Quindi si può settare la immagine dove si vuole (es. icon in JLabel)
E' chiaro che così RIcrei ogni volta una immagine. Chiaramente devi sapere tu quante volte occorre farlo e quando. Ma questo approccio non dà alcuna questione particolare e non richiede alcun accorgimento particolare. Salvo che il set del icon nel JLabel va fatto nel contesto del Event Dispatch Thread. La creazione della immagine invece si potrebbe anche fare in un thread separato per non bloccare la UI.
Altri approcci più sofisticati chiaramente possono richiedere altri accorgimenti e attenzioni particolari.
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Ho tentato a implementare Runnable nella classe Immagine che si occupa di disegnare e restituire l'immagine.
Ed ho messo in void run() lo sleep:
Tuttavia nulla, si blocca sempre il tasto del JPanel.codice:class Immagine implements Runnable { private Graphics g; private BufferedImage image; private Color colore; private Point P; public void run() { while(true) { try { Thread.sleep(100); } catch(Exception ex) {}; } } //altro codice }![]()
jabjoint