[JAVA] JTextArea doet niet live appenden

Pagina: 1
Acties:

  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
Beste mede-gotters.

Ik voer in mijn applicatie een paar processen uit, te weten het verbinding maken met FTP, listen, files downloaden en files importeren in de database.

Ik zou van de voortgang graag de gebruiker op de hoogte houden dmv een JTextArea, zodat hij weet wat er tijdens het wachten gebeurt.

Ik maak dus gebruik van een jTextArea.append("Voortgangregel") na een bepaalde actie (FTP verbinding succesvol, gebruiker x ingelogd, list files, Download OK/Fail... etcetera.
Alleen is het probleem dat de textarea niet na elke append de nieuwe regel weergeeft, maar wacht tot álle acties zijn uitgevoerd en dan in één keer het overzicht van alle tekst weergeeft.
Heb in feite hetzelfde probleem als deze kerel, maar hier werd ook geen oplossing voor gevonden. in dit topic op het java forum wordt gesproken over een extra(?) thread, maar hier kom ik ook niet echt uit.

Iemand suggesties?

Verwijderd

JAVA heeft vast wel een invoke mechanisme waarmee je vanuit een andere thread (FTP verbinding bv.) iets kunt doorgeven aan de main thread waar je jTextArea op draait.

  • gerbennn
  • Registratie: November 2003
  • Laatst online: 10-09 17:42
Verwijderd schreef op maandag 31 maart 2008 @ 01:45:
JAVA heeft vast wel een invoke mechanisme waarmee je vanuit een andere thread (FTP verbinding bv.) iets kunt doorgeven aan de main thread waar je jTextArea op draait.
Jep, dat heet SwingUtilities.invokeLater. :Y)

</signature>


  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Je voert je eigen acties nu waarschijnlijk ook uit op de eventthread (controleren kan met SwingUtilities.isEventThread()), dat behoor je niet te doen. Als je dat namelijk doet kan de interface niet bijgewerkt worden totdat al jouw methodes / acties afgehandeld zijn

Dus: je eigen acties moet je in een nieuwe, losse, thread uitvoeren. Wijzingen aan Swing moet je met SwingUtilities.invokeLater() doorgeven aan de UI. In principe mag JTextArea.append() op iedere willekeurige thread aangeroepen worden, want hij is threadsafe. Dat is echter een uitzondering binnen de Swing-classes/methodes en je kan daarom beter ook die methode op de eventthread aanroepen.

NB: Bedankt voor dit topic, ik zat gisteren ook te klooien met een probleem dat mijn textarea niet werd bijgewerkt (maar dan helemaal niet). Nu nog eens met een frisse blik gekeken en blijkt dat ik mijn JFrame twee keer had aangemaakt en daardoor de verkeerde textarea benaderde :)

[ Voor 17% gewijzigd door Remus op 31-03-2008 10:58 ]


  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
Zal hier morgen eens naar kijken, heb nog geen ervaring daarmee dus kan even duren voordat ik het succesvol geïmplementeerd heb.

  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
Ik kon het toch niet laten om nu al aan de slag te gaan met de gegeven links over invokeLater();

Java:
1
2
3
4
5
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    status.append(tekst);
                }
            });

Is dit een beetje de manier? Ik kan verder weinig goede info vinden.
Hij append wel, maar zelfde als net, nadat de functies zijn uitgevoerd, ik neem aan dat het appenden nu in de methode zelf gebeurt, en wat daarna gebeurt (ftp connectie) in de invoke?

Klinkt misschien een beetje dom, maar ik ben nog niet zo bekend met Threads en dergelijke.

--edit--
Dit nog geprobeerd
Java:
1
2
3
4
5
6
7
8
9
    private void log(String message1) {
        final String message = message1;
        thread = new Thread(new Runnable() {
            public void run() {
                status.append(message);
            }
        });
        thread.start();
    }

In plaats van status.append("String") doe ik nu dus log("String"), helaas met hetzelfde resultaat.

Ik vermoed dat dat komt omdat nu de log() functie in dezelfde Thread wordt aangeroepen.. dat de append een andere Thread krijgt maakt dan natuurlijk geen verschil. Het beste zou dan zijn een while() in de methode te bouwen en deze aan het begin aanroepen. Dan zou het moeten werken denk ik.

[ Voor 35% gewijzigd door Teeno op 01-04-2008 00:51 ]


  • NetForce1
  • Registratie: November 2001
  • Laatst online: 00:12

NetForce1

(inspiratie == 0) -> true

Het idee is dat je de code waardoor log aangeroepen wordt op een andere thread uitvoerd, die code blokkeerd nl. de interface thread.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
Klein schopje... ik kom hier nog steeds niet helemaal uit. Ook als ik de log aanroep vanuit een andere Thread wordt het nog niet live in de textarea gezet.

Wellicht iemand die mij van een klein stukje voorbeeldcode kan voorzien?

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 00:12

NetForce1

(inspiratie == 0) -> true

Zoals ik al zei moet je dus de code die het werk doet op een andere thread draaien.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void doeVeelWerk() {
    new Thread(new Runnable() {
        public void run() {
            // veel werk, loop oid...
            log("veel werk aan het doen...");
        }
    });  
}

private void log(final String msg) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            status.append(msg);
        }
    });
}

Evt kun je hier ook een SwingWorker voor gebruiken, die zit standaard in java6, als je met java5 werkt is er wel ergens een backport te halen op java.net.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Als je meerdere malen feedback vanuit een thread wilt geven, dan is het makkelijker een SwingWorker te gebruiken dan het invokeLater mechanisme.

Wie trösten wir uns, die Mörder aller Mörder?


  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
Ik werk met java6, ik ga hier vanavond naar kijken. bedankt voor de tips

  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
Om deze maar even omhoog te schoppen... ben nu een poosje met SwingWorker aan het spelen, maar krijg het volgende probleem.

Ik heb in een test project deze getest, en werkt prima, een JTextArea wordt goed geüpdate. Nu heb ik dezelfde code gebruikt in mijn main Project maar daar wordt de methode op dezelfde Thread gedraaid.

Java:
1
2
3
4
5
6
7
8
9
10
11
class MySwingWorker extends SwingWorker {
    @Override
    protected Object doInBackground() throws Exception {
        throw new UnsupportedOperationException("Not supported yet.");
    }

// Privates hier
    public MySwingWorker(JTextArea jta) {
    // ...Doe hier heel veel dingen (app bevriest tot alles is uitgevoerd)
    }
}


En deze roep ik op deze manier aan.

Java:
1
2
MySwingWorker swing = new MySwingWorker(jtaConnect);
swing.execute();


Lijkt mij dat dit aardig moet kloppen, maar misschien zie ik iets over het hoofd.

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 00:12

NetForce1

(inspiratie == 0) -> true

Het is dus niet de bedoeling dat je app bevriest als ik het goed begrijp? Dan moet je het zware werk in doInBackground doen in plaats van in de constructor.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
NetForce1 schreef op dinsdag 03 juni 2008 @ 11:06:
Het is dus niet de bedoeling dat je app bevriest als ik het goed begrijp? Dan moet je het zware werk in doInBackground doen in plaats van in de constructor.
Aannemende dat de doInBackground altijd een Object teruggeeft heb ik de code daarin gezet en return null; gegeven. Ik roep hem dan aan dmv swing.doInBackground... de methode wordt wel uitgevoerd, maar de app blijft bevroren. op een of andere manier voert ie de methode dus niet op een andere thread uit, wat wel zou moeten.

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 00:12

NetForce1

(inspiratie == 0) -> true

nee, je moet die methode niet zelf aanroepen, dat gebeurd wanneer je execute aanroept. Zoals volgens mij ook wel duidelijk in de javadoc staat beschreven.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


  • Teeno
  • Registratie: Juni 2007
  • Laatst online: 16-11 19:19
ohw.. ja.. tuurlijk.. :)

Heb de boel werkend, bedankt voor de tips
Pagina: 1