Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1
    Utente di HTML.it
    Registrato dal
    Jul 2009
    Messaggi
    23

    [JAVA] aggiornamento contenuto jTextArea

    Salve a tutti
    Ho questo problema:

    -Ho un ciclo for che scandisce una lista che contiene degli oggetti che rappresentano dei punti
    -Ho una jTextArea su cui voglio scrivere i valori con il metodo append().

    la lista e la jtextArea sono su 2 classi diverse, il ciclo si avvia premendo un bottone che si trova nella classe della jTextArea.
    Io vorrei che i valori vengano scritti passo passo durante il ciclo, invece vengono scritti tutti contemporaneamente quando il ciclo è finito!

    posto il frammento di codice:

    codice:
    for (int i = 0; i < lista.size() - 1; i++) {
    
                //Questo è il punto che dà problemi!!!!!!!
                disegno.jTextArea1.append(lista.get(i).getStringaPunto4() + "\n");
    
                try {//routine di ritardo
                    Thread.sleep(100);
                } catch (Exception e) {
                }
            }
    ho scoperto che qui:

    http://www.javakb.com/Uwe/F o r u m.aspx/java-gui/8316/Update-JTextArea
    (senza spazi)

    hanno il mio stesso problema ma non ho capito bene la soluzione...

    probabilmente è tutto un gioco di thread!!!....qualcuno può aiutarmi???

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [JAVA] aggiornamento contenuto jTextArea

    Originariamente inviato da Anakin84
    probabilmente è tutto un gioco di thread!!!
    Stai già intuendo qualcosa .....

    Quel codice che hai postato lo esegui, deduco, direttamente a seguito dell'evento sul pulsante. Bene, in quel momento (durante la gestione dell'evento) sei nel contesto del EDT (event dispatch thread), il thread che si occupa principalmente di "disegnare" la interfaccia utente e di dispacciare gli eventi. Esso fa solo 1 cosa per volta .... la gestione della interfaccia utente è "single-thread" e basta. Se tieni tu "impegnato" il EDT ..... tutta la tua interfaccia utente è "congelata" e nulla può essere aggiornato/disegnato. Appena termini la gestione dell'evento e il controllo ritorna al framework .... beh, molto prontamente scopre che c'è qualcosa da aggiornare e allora "vedi" le modifiche.

    Morale: non tenere impegnato per troppo tempo il EDT, non fare sleep() o cose simili nel contesto del EDT.

    Crea un nuovo thread. E ti va bene, perché append() di JTextArea è uno di quei metodi indicati come "thread-safe", puoi anche invocarlo non dal EDT.
    La regola generale in Swing è che l'accesso ai componenti della interfaccia utente va fatto solo dal EDT. append() è una delle eccezioni.

    E suggerisco la lettura di:
    Concurrency in Swing
    Threads and Swing
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Jul 2009
    Messaggi
    23
    Capito!....e quindi come risolvo??

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Anakin84
    Capito!....e quindi come risolvo??
    Crea un nuovo thread o eventualmente usa un "timer" (ci sono 2 timer: java.util.Timer e javax.swing.Timer, sono ben diversi come concetti e struttura).

    Per l'append() come ho detto non ci sono problemi .... è "thread-safe". Qualunque altra cosa non è detto che lo sia anche ... bisogna vedere. In particolare vedo che fai un lista.get(i). Quel 'lista' cosa è? Un ArrayList o un Vector (o altra lista)? Vector è "synchronized" quindi non ci sarebbero problemi se ad esempio scrivi elementi dal EDT e poi li leggi da un "tuo" thread.

    Quello che vorrei farti capire è che qui si entra in un argomento molto delicato che è quello dei thread, concorrenza, sincronizzazione, thread-safety e altro. Se non si hanno le idee chiare, si rischia di fare cose concettualmente sbagliate (come quello che stavi facendo) o cose che funzionano 99 volte sì e 1 volta no per via di tempistiche "sfortunate" tra i vari thread.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Jul 2009
    Messaggi
    23
    La lista è un ArrayList, sostituisco con vector??

    per il resto dovrei scrivere una cosa del tipo

    codice:
    java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    disegno.jTextArea1.append(lista.get(i).getStringaPunto4() + "\n");
                }
            });
    scusa, ma non sono molto esperto di multi threading (grazie per l'interessamento comunque!!)

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Anakin84
    La lista è un ArrayList, sostituisco con vector??

    per il resto dovrei scrivere una cosa del tipo

    codice:
    java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    disegno.jTextArea1.append(lista.get(i).getStringaPunto4() + "\n");
                }
            });
    Questo potresti farlo all'interno del run() per un "tuo" thread, dove fai un po' lo sleep() e un po' questo invokeLater() (ripetuto in ciclo). Dal momento che get() e append() li fai "passare" nel EDT, non ci sarebbero problemi (per append() no di certo visto che è thread-safe e per la lista nemmeno se aggiungi elementi dal EDT).

    Se usassi un timer sarebbe ancora più semplice (non hai bisogno di sleep()) ma ovviamente devi tenerti la informazione dell'indice da qualche parte.

    Se la lista la modifichi dal EDT e non vuoi usare questo invokeLater() in un "tuo" thread, allora sì sarebbe meglio usare Vector.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it
    Registrato dal
    Jul 2009
    Messaggi
    23
    Ho provato ma non cambia nulla....non è che puoi postare un codice d'esempio...???

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Anakin84
    Ho provato ma non cambia nulla....
    Ma dipende da cosa hai scritto ....

    Lo ripeto meglio: tu vuoi aggiungere delle righe in una text area. Ma non tutte d'un colpo .... in modo "rallentato" ogni "tot" di tempo e ogni aggiunta vuoi che sia visibile immediatamente.

    Il concetto di "ogni tot di tempo" lo puoi fare generalmente in 2 modi: con un "timer" oppure con un tuo thread in cui fai esattamente il ciclo che avevi postato all'inizio (un append, poi un sleep, poi un append ecc.... in ciclo).

    Se usi un javax.swing.Timer, l'evento è dispacciato nel EDT, quindi non ci sono problemi. Se usi un "tuo" thread, devi creare un Thread (o estendi Thread e implementi run() oppure implementi un Runnable con run() e poi lo passi a Thread) e farlo partire.
    In questo caso sei nel "tuo" thread, non nel EDT. Quindi c'è da fare attenzione E per append() no problem.

    Ti è più chiaro?
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Utente di HTML.it
    Registrato dal
    Jul 2009
    Messaggi
    23
    Siccome stavo letteralmente impazzendo con questi thread ho tolto la jTextArea e ho creato una classe PannelloTextArea che estende jPanel su cui disegno con l'oggetto grafico Graphics g quindi ora il codice diventa:

    codice:
    for (int i = 0; i < lista.size() - 1; i++) {
                
                pannello.setLine(pannello.getGraphics(), lista.get(i), lista.get(i + 1));
    
                //setPunto richiama il metodo drawString
                pannelloTesto.setPunto(pannelloTesto.getGraphics(), lista.get(i),(i+1)*15);
                
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                }
    
            }
    ed ora finalmente i punti vengono aggiornati durante l'esecuzione del ciclo!!!

    L'unico problema ora è che i punti da stampare sono tanti e superano la dimensione del pannello. C'è un qualche modo per abilitare lo Scroll del pannello in modo da poter scorrerlo tutto??

  10. #10
    Utente di HTML.it
    Registrato dal
    Jul 2009
    Messaggi
    23
    Sono tornato alla jTextArea e ho risolto così:

    codice:
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowEvent;
    
    import javax.swing.DefaultListModel;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JList;
    import javax.swing.JPanel;
    
    public class Prova extends JFrame {
    
        public class Lavoratore extends Thread {
            /*creare il nuovo thread estendendo Thread e non implementando
            Runnable, così posso chiamare il metodo start 
            perche il run non va bene*/
    
            DefaultListModel ml;
    
            public Lavoratore(DefaultListModel ml) {
                this.ml = ml;
            }
    
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    ml.addElement("ciao");
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
    
            }
        }
    
        public static void main(String o[]) {
            Prova x = new Prova();
            x.setVisible(true);
        }
        JPanel principale;
        BorderLayout gestorePrincipale;
        DefaultListModel modelloLista = new DefaultListModel();
        JList lista = new JList(modelloLista);
        JButton esegui = new JButton("esegui");
    
        public Prova() {
            principale = new JPanel();
            gestorePrincipale = new BorderLayout();
    
            principale.setLayout(gestorePrincipale);
            this.getContentPane().add(principale);
            principale.add(lista, BorderLayout.CENTER);
            principale.add(esegui, BorderLayout.SOUTH);
    
            this.setSize(300, 500);
            this.validate();
    
            esegui.addActionListener(new ActionListener() {
    
                public void actionPerformed(ActionEvent e) {
                    premuto();
                }
            });
    
        }
    
        @Override
        protected void processWindowEvent(WindowEvent e) {
            super.processWindowEvent(e);
            if (e.getID() == WindowEvent.WINDOW_CLOSING) {
                System.exit(0);
            }
        }
    
        public void premuto() {
            Lavoratore l = new Lavoratore(modelloLista);
            l.start();
        }
    }
    Grazie a tutti quelli che hanno risposto

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.