Textausgabe erzwingen

Status
Nicht offen für weitere Antworten.
B

benny!

Gast
Hallo,

ich habe in meiner Gui ein JTextArea als Statusfenster implementiert. In diesem möchte
ich dann gewisse Statusmeldungen erscheinen lassen. Wenn ich jetzt jedoch eine Funktion
aufrufe, die ein wenig Rechenzeit benötigt, zu unterschiedlichen Zeitpunkten jedoch Text
in die JTextArea schreibt, wird der komplette Text erst nach Beenden der Methode ange-
zeigt.

Diese Methode als Thread laufen zu lassen, hat leider auch nichts gebracht :-(

Hiermal in Pseudo-Code worum es geht :

Code:
class Thread {


   run {

      zeitIntensiveMethode()
   
   }


   zeitIntensiveMethode() {

   rechne...
   TextAusgabe()
   rechne....
   TextAusgabe()

   }

}

class main {

   new Thread.start()
   while ( Thread.isAlive() ) {}

}

Ich habe auch schon versucht, ein repaint nach jeder TextAusgabe des JTextArea
Gadgets zu erzwingen, leider auch ohne Erfolg. Daran müsste es aber irgendwie liegen,
denn wenn ich die Zeit tracke, wann der Text in das JTextArea Gadget geschrieben wird,
dann sieht man, dass sie alle zu unterschiedlichen Zeiten geschrieben wurden.

Desweiteren kommt es bei einer reinen Textausgabe via System.out.print nicht zu
diesem Problem :?:

Bin für jede Hilfe dankbar ???:L
 
B

benny!

Gast
Wildcard hat gesagt.:
Wahrscheinlich blockierst du den AWT-Event-Dispatch Thread.

Ich glaube daran könnte es liegen. Nachdem was ich im Internet gefunden habe,
sollte sich mein Problem dann mittels SwingUtilities.invokeLater() beheben
lassen - hat aber leider noch nicht funktioniert :-( ...

Weitere Tipps werden gerne entgegengenommen ;-)
 

Wildcard

Top Contributor
Das kann nicht funktionieren da der EventDispatcher ja blockiert ist :wink:
Zeig mal Code.
 
B

benny!

Gast
Wildcard hat gesagt.:
Das kann nicht funktionieren da der EventDispatcher ja blockiert ist :wink:
Zeig mal Code.

Hat doch funktioniert. Ich hatte das mit dem EventDispatcher zunächst falsch verstanden
und die Textausgabe-Klasse mittels SwingUtilities.invokeLater() aufgerufen.

Man muss aber logischerweise die zeitintensive Klasse / Methode aufrufen.

[codeauschnitt]
Code:
Generator gen = new Generator( pdf );
SwingUtilities.invokeLater( gen );
//normale Textausgaben erfolgen ab hier wie gewünscht und relativ zeitnah

Wobei Generator vom Thread erbt und demnach 'ne run Methode hat. Nochmals
danke für den Tipp mit dem EventDispatcher ... hat mir gut weitergeholfen :applaus:
 

Wildcard

Top Contributor
benny! hat gesagt.:
Man muss aber logischerweise die zeitintensive Klasse / Methode aufrufen.
Achtung! Wenn du deinen Zeitintensiven Task mit invokeLater startest, dann läuft dieser im EDT. Das RUnnable wird einfach in die Queue eingereiht. Das bedeutet das deine GUI nicht mehr richtig reagiert solange der Task ausgeführt wird.
 

André Uhres

Top Contributor
"invokeLater" soll man aufrufen, wenn ein Anwendungsthread die GUI verändern will:
Code:
package text;
/*
 * StatusfensterDemo.java
 */
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class StatusfensterDemo extends JFrame {
    private JButton btStart;
    private JDialog statusFenster;
    private JTextArea textarea;
    private JToolBar toolbar;
    public StatusfensterDemo() {
        super("Statusfenster Demo");
        setSize(400,300);
        setLocationRelativeTo(null);
        statusFenster = new JDialog(this);
        textarea = new JTextArea();
        toolbar = new JToolBar();
        btStart = new JButton("Start");
        textarea.setBackground(new Color(255, 255, 204));
        textarea.setEditable(false);
        statusFenster.setTitle("Status Fenster");
        statusFenster.getContentPane().add(new JScrollPane(textarea), BorderLayout.CENTER);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        toolbar.add(btStart);
        getContentPane().add(toolbar, BorderLayout.NORTH);
        btStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                btStartActionPerformed(evt);
            }
        });
    }
    private void btStartActionPerformed(final ActionEvent evt) {
        new Thread(new Runnable() {
            public void run() {
                statusFenster.setSize(300,200);
                statusFenster.setVisible(true);
                for (int i = 0; i < 15; i++) {
                    try {Thread.sleep(500);} catch (InterruptedException ex) {}
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            textarea.append(new Date()+"\n");
                            textarea.setCaretPosition(textarea.getText().length());
                        }
                    });
                }
                try {Thread.sleep(1000);} catch (InterruptedException ex) {}
                statusFenster.setVisible(false);
            }
        }).start();
    }
    public static void main(final String args[]) {new StatusfensterDemo().setVisible(true);}
}
 
B

benny!

Gast
Wildcard hat gesagt.:
benny! hat gesagt.:
Man muss aber logischerweise die zeitintensive Klasse / Methode aufrufen.
Achtung! Wenn du deinen Zeitintensiven Task mit invokeLater startest, dann läuft dieser im EDT. Das RUnnable wird einfach in die Queue eingereiht. Das bedeutet das deine GUI nicht mehr richtig reagiert solange der Task ausgeführt wird.

Da haste recht. Gui reagiert nur in sofern, dass ich sie resizen / bewegen kann.
Möchte ich beispielsweise eine Scrollleiste bewegen, reagiert sie nicht.

Hmm ... für mein spezielles Problem ist das nicht so wichtig ( mir genügt es in
meinem StatusTextFeld "bitte warten" auszugeben ;-) ).

Allgemein würde ich es aber schon interessieren, wie man es alternativ lösen
könnte :?:
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben