|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Jun 2005
Messaggi: 99
|
[JAVA] Aggiornare immediatamente il JPanel
Ciao a tutti.
Nell'applicazione che sto ultimando avrei bisogno di far accendere una JLabel di Please Waiting mentre si sta eseguendo l'algoritmo e farla spegnere al termine del calcolo. Ho implementato il tutto in questo modo: Codice:
pleaseWaitLabel.setEnabled(true); repaint(); revalidate(); //Istruzioni che richiamano vari metodi per eseguire l'algoritmo principale pleaseWaitLabel.setEnabled(false); repaint(); revalidate(); Come potrei risolvere? Esiste in alternativa una finestra da far comparire (stile JOptionPane) e chiudere automaticamente alla fine dell'eleborazione? Grazie anticipatamente. Ciao, Francesco |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Guarda qua che fa revalidate().
Inoltre non dovrebbe essere neccessario chiamarlo. Hai già provato così: Codice:
pleaseWaitLabel.setEnabled(true); repaint(); //Istruzioni che richiamano vari metodi per eseguire l'algoritmo principale pleaseWaitLabel.setEnabled(false); repaint(); Puoi postare uno spezzone maggiore del codice?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 27-10-2008 alle 17:57. |
![]() |
![]() |
![]() |
#3 | ||
Member
Iscritto dal: Jun 2005
Messaggi: 99
|
We, ciao banryu!
![]() Quote:
Quote:
Ecco altro codice (posto l'intera azione del listener): Codice:
if(e.getSource() == computeButton) { int numRepetitions = -1; int acyclic = 0; try { if (getRepetitions() > 0) numRepetitions = getRepetitions(); else JOptionPane.showMessageDialog(null, "<html><body>The format is not valid!<br>" + "Please enter a positive integer<br>" + "and less than 2147483648.</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } catch(NumberFormatException exception) { JOptionPane.showMessageDialog(null, "<html><body>The format is not valid!<br>" + "Please enter a positive integer<br>" + "and less than 2147483648.</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } pleaseWaitLabel.setEnabled(true); //Refresh MainPanel repaint(); revalidate(); if(numRepetitions > 0) { ArrayList<ArrayList<Object>> dataActArray = new ArrayList<ArrayList<Object>>(); dataActArray = getDataAct(); if(dataActArray.get(0).size() > 1) { startSimulations = System.currentTimeMillis(); MCSimulation mcs = new MCSimulation(numRepetitions, dataActArray); acyclic = mcs.topologicalSort(); if(acyclic == 1) { System.out.println("Array (prima colonna) ordinato topologicamente:"); mcs.printSortArray(); mcs.makeInNodes(); System.out.println(); System.out.println("Matrice inNodes:"); mcs.printInNodes(); System.out.println(); System.out.println("Array inDegree:"); mcs.printInDegree(); System.out.println(); System.out.println(); mcs.simulations(); stopSimulations = System.currentTimeMillis(); } else { stopSimulations = System.currentTimeMillis(); JOptionPane.showMessageDialog(null, "<html><body>The following activities make a cyclical project!!!<br>" + "Please check all precedences in the activities!!!</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } timeSpentField.setText(""+((double)(stopSimulations-startSimulations)/1000)); } else { System.out.println("Error: ci sono state delle eccezioni!"); } } pleaseWaitLabel.setEnabled(false); //Refresh MainPanel repaint(); revalidate(); } |
||
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Dato che lo spezzone di codice postato è quello contenuto in un Listener significa che il Thread in cui viene processato è l'EDT.
L'EDT (Event Dispatching Thread) è il Thread di AWT che processa eventi AWT, per l'appunto. AWT usa un modello di painting a thread singolo dove tutti gli aggiornamenti della grafica vengono processati in un singolo Thread. L'EDT è l'unico thread valido da cui poter aggiornare lo stato visibile dell'interfaccia grafica utente. Questo implica, tra l'altro, che aggiornare la grafica da altri thread diversi dall'EDT può essere causa di comportamenti anomali e funzionamenti non corretti dell'interfaccia grafica. C'è poi anche il rovescio della medaglia da considerare. E cioè far eseguire all'EDT anche troppo lavoro (per esempio l'esecuzione di un algoritmo o dell'altro codice "che porta via tempo") col rischio di appesantire la velocità di risposta dell'interfaccia grafica. Venendo al punto: dato che subito prima di eseguire l'algoritmo vuoi abilitare una JLabel disbilitata, e che nel farlo poi chiami di fila a repaint() un revalidate(), e che leggendo la documentazione a proposito di revalidate() notiamo che dice: Quote:
Potrestri provare a inserire il codice relativo al tuo algoritmo nel metodo run() di un altro thread creato al volo. Puoi fare una cosa del genere: Codice:
Thread algoThread = new Thread() { public void run() { // codice algoritmo } }; algoThread.start(); Ah, prima volevo farti una domanda: perchè la JLabel segli di abilitarla (setEnable), invece di renterla semplicemente visibile e invisibile (setVisible)?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Jun 2005
Messaggi: 99
|
Capisco, sei stato molto chiaro.
Il problema che mi si presenta però è che avendo variabili dichiarate esternamente (come numRepetitions) mi suggerisce di dichiararle "final" (cosa che naturalmente non posso fare) affinchè il thread possa "usufruirne". Come posso aggirare questo problema? Altrimenti devo inglobare dentro il thread tutto il codice che viene eseguito cliccando sul pulsante Compute (e non solo l'algoritmo) TRANNE le istruzioni per la JLabel... P.S. setVisible è infatti la soluzione finale. Per provare però ho volutamente utilizzato setEnabled, in modo da esser sicuro (vedendo sia la parte spenta che accesa) che tutto funzionasse a dovere... cosa che fin'ora non è accaduto! ![]() Ultima modifica di pumax84 : 28-10-2008 alle 12:23. |
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
![]() Prova con setVisible() e senza la chiamata a revalidate(). @EDIT: in ogni caso devi delegare ad un altro thread (esterno quindi all'EDT) l'esecuzione dell'algoritmo.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 28-10-2008 alle 15:32. |
|
![]() |
![]() |
![]() |
#7 | ||
Member
Iscritto dal: Jun 2005
Messaggi: 99
|
Quote:
![]() Quote:
![]() Ecco il codice: Codice:
if(e.getSource() == computeButton) { Thread algorithmThread = new Thread() { @Override public void run() { int numRepetitions = -1; int acyclic = 0; try { if (getRepetitions() > 0) numRepetitions = getRepetitions(); else JOptionPane.showMessageDialog(null, "<html><body>The format is not valid!<br>" + "Please enter a positive integer<br>" + "and less than 2147483648.</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } catch(NumberFormatException exception) { JOptionPane.showMessageDialog(null, "<html><body>The format is not valid!<br>" + "Please enter a positive integer<br>" + "and less than 2147483648.</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } if(numRepetitions > 0) { ArrayList<ArrayList<Object>> dataActArray = new ArrayList<ArrayList<Object>>(); dataActArray = getDataAct(); if(dataActArray.get(0).size() > 1) { results = new ArrayList<Object>(); startSimulations = System.currentTimeMillis(); MCSimulation mcs = new MCSimulation(numRepetitions, dataActArray); acyclic = mcs.topologicalSort(); if(acyclic == 1) { System.out.println("Array (prima colonna) ordinato topologicamente:"); mcs.printSortArray(); mcs.makeInNodes(); System.out.println(); System.out.println("Matrice inNodes:"); mcs.printInNodes(); System.out.println(); System.out.println("Array inDegree:"); mcs.printInDegree(); System.out.println(); System.out.println(); System.out.println("Array outDegree:"); mcs.printOutDegree(); System.out.println(); System.out.println(); results = mcs.simulations(); stopSimulations = System.currentTimeMillis(); DecimalFormatSymbols symb = new DecimalFormatSymbols(); symb.setDecimalSeparator('.'); DecimalFormat df = new DecimalFormat(); df.setDecimalFormatSymbols(symb); df.setMaximumFractionDigits(3); timeSpentField.setText(""+((double)(stopSimulations-startSimulations)/1000)); maxTotalDurField.setText(""+df.format(results.get(0))); sdField.setText(""+df.format(results.get(1))); for(int i=0; i<activitiesNumber; i++) { ((JTextField)activitiesArray.get(i).get(5)).setText(""+((int[])results.get(2))[i]); } } else { stopSimulations = System.currentTimeMillis(); JOptionPane.showMessageDialog(null, "<html><body>The following activities make a cyclical project!!!<br>" + "Please check all precedences in the activities!!!</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } } else { System.out.println("Error: ci sono state delle eccezioni!"); } } pleaseWaitLabel.setVisible(false); //Refresh MainPanel repaint(); } }; pleaseWaitLabel.setVisible(true); //Refresh MainPanel repaint(); algorithmThread.start(); } Ultima modifica di pumax84 : 29-10-2008 alle 14:33. |
||
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Bene, ora, fossi in te, rifattorizzerei quel "bloccone" di codice che viene eseguito nel thread esterno, se non altro per migliorare la leggibilità.
Ciao ![]() @EDIT: Ehm, c'è ancora qualcosa di 'sporco': fai processare al thread esterno del codice AWT (ovvero quando setti la JLabel a non visibile). Come detto sopra: L'EDT è l'unico thread valido da cui poter aggiornare lo stato visibile dell'interfaccia grafica utente. Questo implica, tra l'altro, che aggiornare la grafica da altri thread diversi dall'EDT può essere causa di comportamenti anomali e funzionamenti non corretti dell'interfaccia grafica. Per ovviare dovresti far accodare l'operazione nella AWT Event Queue, come? Usando il metodo SwingUtilities.InvokeLater(Runnable) a cui passi un thread (un Runnable) che puoi anche creare on the fly come hai fatto sopra, il cui scopo è appunto quello di invocare setVisible() sulla JLabel.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 29-10-2008 alle 14:50. |
![]() |
![]() |
![]() |
#9 | ||
Member
Iscritto dal: Jun 2005
Messaggi: 99
|
Quote:
![]() Quote:
![]() Ah, dato che ci siamo... ![]() ![]() |
||
![]() |
![]() |
![]() |
#10 | ||
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Codice:
Runnable hideAndUpdate = new Runnable() { public void run() { pleaseWaitLabel.setVisible(false); repaint(); } }; SwingUtilities.invokeLater(hideAndUpdate); Quote:
Vai a vedere quali classi implementano RandomStream; ancora meglio trova, se esistono, tutorial ed esempi di utilizzo di quella libreria (magari partendo dal sito dove l'hai trovata).
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
||
![]() |
![]() |
![]() |
#11 | ||
Member
Iscritto dal: Jun 2005
Messaggi: 99
|
Quote:
Quote:
![]() |
||
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Provo a schematizzare: Codice:
-> chiamata ActionListener [thread corrente: EDT] | ---> esecuzione algoritmo [thread corrente: esterno] | ---> nascondere JLabel [thread corrente: esterno] Da cui la neccessità di accodare nell'Event Queue (perchè così verrà eseguito dall'EDT) il codice che "nasconde" la label e richiede un repaint.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#13 |
Member
Iscritto dal: Jun 2005
Messaggi: 99
|
Ah ecco... Io avevo già provato in quel modo, ma la dichiarazione/inizializzazione del Runnable la facevo esterna al Thread, di conseguenza mi indicava che non riconosceva la variabile...
![]() ![]() Ora l'ho messa all'interno e sembra andare. Incollo il codice per una conferma sulla correttezza! ![]() Codice:
if(e.getSource() == computeButton) { Thread algorithmThread = new Thread() { @Override public void run() { Runnable hideAndUpdate = new Runnable() { public void run() { pleaseWaitLabel.setVisible(false); repaint(); } }; int numRepetitions = -1; int acyclic = 0; try { if (getRepetitions() > 0) numRepetitions = getRepetitions(); else JOptionPane.showMessageDialog(null, "<html><body>The format is not valid!<br>" + "Please enter a positive integer<br>" + "and less than 2147483648.</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } catch(NumberFormatException exception) { JOptionPane.showMessageDialog(null, "<html><body>The format is not valid!<br>" + "Please enter a positive integer<br>" + "and less than 2147483648.</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } if(numRepetitions > 0) { ArrayList<ArrayList<Object>> dataActArray = new ArrayList<ArrayList<Object>>(); dataActArray = getDataAct(); if(dataActArray.get(0).size() > 1) { results = new ArrayList<Object>(); startSimulations = System.currentTimeMillis(); MCSimulation mcs = new MCSimulation(numRepetitions, dataActArray); acyclic = mcs.topologicalSort(); if(acyclic == 1) { System.out.println("Array (prima colonna) ordinato topologicamente:"); mcs.printSortArray(); mcs.makeInNodes(); System.out.println(); System.out.println("Matrice inNodes:"); mcs.printInNodes(); System.out.println(); System.out.println("Array inDegree:"); mcs.printInDegree(); System.out.println(); System.out.println(); System.out.println("Array outDegree:"); mcs.printOutDegree(); System.out.println(); System.out.println(); results = mcs.simulations(); stopSimulations = System.currentTimeMillis(); DecimalFormatSymbols symb = new DecimalFormatSymbols(); symb.setDecimalSeparator('.'); DecimalFormat df = new DecimalFormat(); df.setDecimalFormatSymbols(symb); df.setMaximumFractionDigits(3); timeSpentField.setText(""+((double)(stopSimulations-startSimulations)/1000)); maxTotalDurField.setText(""+df.format(results.get(0))); sdField.setText(""+df.format(results.get(1))); for(int i=0; i<activitiesNumber; i++) { ((JTextField)activitiesArray.get(i).get(5)).setText(""+((int[])results.get(2))[i]); } } else { stopSimulations = System.currentTimeMillis(); JOptionPane.showMessageDialog(null, "<html><body>The following activities make a cyclical project!!!<br>" + "Please check all precedences in the activities!!!</body></html>", "Error", JOptionPane.ERROR_MESSAGE); } } else { System.out.println("Error: ci sono state delle eccezioni!"); } } SwingUtilities.invokeLater(hideAndUpdate); } }; pleaseWaitLabel.setVisible(true); //Refresh MainPanel repaint(); algorithmThread.start(); } |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 17:50.