Performance-Problem: JTextArea als Logging-Window

Status
Nicht offen für weitere Antworten.
S

Sven Z.

Gast
Hallo *.*,

ich habe mir eine kleine Swing-Anwendung geschrieben, die viele Statusmeldungen ausgibt. Damit das möglichst komfortabel und schön ist, habe ich mir dazu eine von JFrame abgeleitete Klasse geschrieben:

Code:
public class WndLogging extends JFrame implements java.lang.Runnable
{	
	private javax.swing.JPanel jContentPane = null;

	private javax.swing.JScrollPane jScrollPane = null;
	private javax.swing.JTextArea taLogging = null;

	public WndLogging()
	{
		super();

		setVisible(false);
		setResizable(false);
		setTitle("Log-Window");
		setLocation(545,100);
		setSize(545, 328);

		taLogging = new javax.swing.JTextArea();
		jScrollPane = new javax.swing.JScrollPane();
		jContentPane = new javax.swing.JPanel();

		jScrollPane.setViewportView(taLogging);
		jScrollPane.setBounds(0, 0, 537, 303);

		jContentPane.setLayout(null);
		jContentPane.add(jScrollPane, null);
		setContentPane(jContentPane);
	}

	private String getFullFormat(String str)
	{
		String erg = null;
		if (str.trim().length() == 1)
		{
			erg = new String("0"+str);
		}
		else
			erg = new String(str);
		return erg;		
	}

	private String getDateTime()
	{
		StringBuffer sb = new StringBuffer("[ ");
		java.util.Calendar rightNow = java.util.Calendar.getInstance();
		String year = new String(""+rightNow.get(java.util.Calendar.YEAR));
		String month = getFullFormat(new String(""+rightNow.get(java.util.Calendar.MONTH)));
		String day = getFullFormat(new String(""+rightNow.get(java.util.Calendar.DAY_OF_MONTH)));
		String hour = getFullFormat(new String(""+rightNow.get(java.util.Calendar.HOUR_OF_DAY)));
		String minute = getFullFormat(new String(""+rightNow.get(java.util.Calendar.MINUTE)));
		String second = getFullFormat(new String(""+rightNow.get(java.util.Calendar.SECOND)));
		
		return sb.append(year).append("-").append(month).append("-").append(day).append(" ").append(hour).append(":").append(minute).append(":").append(second).append(" ] ").toString();
	}
	
	public void addMessage(String str)
	{
		StringBuffer sb = new StringBuffer(getDateTime()); 

		if (str.indexOf("\n") == -1)
		{
			sb.append(str);
			sb.append("\n");
			
			taLogging.insert(sb.toString(),taLogging.getText().length());
			return;
		}

		java.util.StringTokenizer st = new java.util.StringTokenizer(str,"\n");
		if (st.countTokens()>0)
		{
			while (st.hasMoreTokens()) {
				taLogging.insert(getDateTime()+st.nextToken()+"\n",taLogging.getText().length());
			}
		}
	}

	public void run() {
		this.setVisible(true);
	}
     
}

In meiner Applikation starte initialtisiere ich das Fenster folgendermaßen:
Code:
		frmLogging = new WndLogging();
		new Thread(frmLogging).start();

Anschließend knall ich im ms-Takt Nachrichten in mein Log-Fenster
Code:
frmLogging.addMessage("bla");

Leider wird die JTextArea erst gefüllt, nachdem das ganze Programm durchgelaufen ist. Ich verstehe leider nicht warum das so ist, und vorallem, wie ich das verhindern könnte. Ich möchte nämlich das ich die Statusmeldungen sehe als bald ich sie zugefügt habe.

Ich hoffe ihr versteht mich und könnt mir irgendwie helfen! Ich würde mich darüber jedenfalls sehr freuen! :)
 

Mizus

Bekanntes Mitglied
Fügst du den nur String hinzu?? Wenn ja dann geht das auch so..

Code:
JTextarea myTextarea = new Textarea();
// Das \n ist wichtig da sonst immer neben einander geschrieben werden würde.
myTextarea.setText(myTextarea.getText() + "Hallo\n");

mfg mizus
 

svenz

Mitglied
Nein, ich füge noch einen Timestamp zu, und muss das auch bei Zeilenumbrüchen machen.

Aber steht ja alles in meinem Code, vielleicht sollte man sich den doch mal angucken bevor man antwortet. ;)
 

svenz

Mitglied
So, ich habe die Klasse nochmal neu geschrieben, das alte konnte so mit den Threads nicht funktionieren.

Jetzt läuft zwar die Protokollierung als eigener Thread, aber die GUI updated sich trotzdem nicht wie gewünscht bei jedem Einfügen einer Statusmeldung, sondern erst wenn das Programm fertig ist. In der Konsole funktioniert das Logging wie gewünscht...

Code:
public class WndLogging extends JFrame implements java.lang.Runnable
{	
	private javax.swing.JPanel jContentPane = null;
	private javax.swing.JScrollPane jScrollPane = null;
	private javax.swing.JTextArea taLogging = null;

	private Vector messages = null;

	public WndLogging()
	{
		super();

		setVisible(false);
		setResizable(false);
		setTitle("Log-Window");
		setLocation(545,100);
		setSize(545, 328);

		taLogging    = new javax.swing.JTextArea();
		jScrollPane  = new javax.swing.JScrollPane();
		jContentPane = new javax.swing.JPanel();

		jScrollPane.setViewportView(taLogging);
		jScrollPane.setBounds(0, 0, 537, 303);

		jContentPane.setLayout(null);
		jContentPane.add(jScrollPane, null);
		setContentPane(jContentPane);
		
		messages = new Vector(); 
	}

	private String getFullFormat(String str)
	{
		String erg = null;
		if (str.trim().length() == 1)
		{
			erg = new String("0"+str);
		}
		else
			erg = new String(str);
		return erg;		
	}

	private String getDateTime()
	{
		StringBuffer sb = new StringBuffer("[ ");
		java.util.Calendar rightNow = java.util.Calendar.getInstance();
		String year = new String(""+rightNow.get(java.util.Calendar.YEAR));
		String month = getFullFormat(new String(""+rightNow.get(java.util.Calendar.MONTH)));
		String day = getFullFormat(new String(""+rightNow.get(java.util.Calendar.DAY_OF_MONTH)));
		String hour = getFullFormat(new String(""+rightNow.get(java.util.Calendar.HOUR_OF_DAY)));
		String minute = getFullFormat(new String(""+rightNow.get(java.util.Calendar.MINUTE)));
		String second = getFullFormat(new String(""+rightNow.get(java.util.Calendar.SECOND)));
		
		return sb.append(year).append("-").append(month).append("-").append(day).append(" ").append(hour).append(":").append(minute).append(":").append(second).append(" ] ").toString();
	}
	
	public void addMessage(String str)
	{
		if (str.indexOf("\n") == -1)
		{
			messages.addElement(new String(getDateTime()+str+"\n"));
		}
		else
		{
			java.util.StringTokenizer st = new java.util.StringTokenizer(str,"\n");
			if (st.countTokens()>0)
			{
				while (st.hasMoreTokens()) {
					messages.addElement(new String(getDateTime()+st.nextToken()+"\n"));
				}
			}
		}

		synchronized (this)
		{
			notifyAll();
		}
	}

	public void run() {
		this.setVisible(true);
		
		while (true)
		{
			synchronized(this)
			{
				try
				{
					wait();

					while (messages.size()>0)
					{
						taLogging.insert((String)messages.elementAt(0),taLogging.getText().length());
						System.out.println((String)messages.elementAt(0));
						messages.removeElementAt(0);
					}
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
		}
	}
     
}
 
G

Guest

Gast
Hallo,

Du darfst niemals die GUI außerhalb des Dispatcher-Threads ändern.
Im Dispatcher-Thread ist man z.B., wenn man ein Eventhandler ist (also ein Listener) und gerade benachrichtigt
wird.
Hintergrund: Swing packt alle Events (Tastendruck, Textänderung, Mouse, ...) in eine Queue. Der Dispatcher arbeitet sie der Reihe nach ab. Wenn Du nun in einem solchen Event eine Aktion abarbeitest, bist Du im Dispatcher-Thread.
Folglich kann dieser seiner Aufgabe nicht nachkommen. Die Events bleiben liegen, bis Deine Aufgabe fertig ist.

Ich würde Dir empfehlen, zunächst Deinen Thread für das GUI-Update zu entfernen. Du brauchst nicht wirklich eine Queue, genausogut kannst Du die Infos in die TextArea direkt einfügen. Das mit wait() und notify() ist zwar sehr
schön, aber wozu einen Thread zwischenschalten, wenn man das nicht muss?

Als nächstes musst Du dafür sorgen, dass Deine eigentliche Aktion (Erzeuger der Logmeldungen) in einem eigenen
Thread läuft. Vermutlich ist Dein Problem bisher, dass der Anwender irgendwo auf einen Button drückt, woraufhin die
Aktion synchron (also im Dispatcher-Thread läuft). Während dessen kann natürlich die GUI nicht neu gezeichnet werden.
Kapsele daher den Aufruf starteAktion() (oder wie immer auch das heißt) in einen Thread und starte den.
Damit kann der Dispatcher (parallel) seiner eigentlichen Arbeit nachgehen - Events ausliefern.

Die Sache hat allerdings einen Haken, Updates darf wieder nur der DispatcherThread machen.
Dafür sieht Swing die Möglichkeit vor, Aktionen innerhalb der EventQueue laufen zu lassen.
Immer wenn Du also die GUI änderst, in Deinem Fall die TextArea, musst Du die Änderung in ein
Runnable r verpacken und mit SwingUtilities.invokeLater(r) aufrufen.
Damit wird die Änderung (wie jedes Event) durch den EventDispatcher-Thread ausgeführt - Die GUI lebt.

Hinweis: Wenn man Swing threaded, muss man sich um die wilden Eingaben des Benutzers natürlich mehr kümmern!

Hier noch Links:

http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

http://java.sun.com/developer/technicalArticles/Threads/swing/?frontpage-jdc

Gruß,

Karl
 

svenz

Mitglied
Hallo Karl,

vielen Dank für Deinen Beitrag. Dank Deiner ausführlichen Hilfe (und den Links) konnte ich dieses wirklich lästige Problem lösen. :):toll:

Gruß,
Sven
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
T Swing Allgemeines Problem mit der Performance bei DragAndDrop AWT, Swing, JavaFX & SWT 2
T Prüfen ob 2 JLabel übereinander liegen. Performance Problem. AWT, Swing, JavaFX & SWT 5
C Performance-Problem beim Überschreiben von paintComponent() AWT, Swing, JavaFX & SWT 2
D performance problem: paintcomponent, alphacomp, bufferedImag AWT, Swing, JavaFX & SWT 10
T Performance Problem bei BufferedImage AWT, Swing, JavaFX & SWT 3
F Problem mit Transparenz, MouseEvents und Performance AWT, Swing, JavaFX & SWT 3
H Viele ActionListener (MouseListener) - Performance AWT, Swing, JavaFX & SWT 24
missy72 JavaFX Performance / ImageView in TableView über TimeLine AWT, Swing, JavaFX & SWT 1
L JavaFX ListCell Performance AWT, Swing, JavaFX & SWT 10
E Swing Miserable Performance beim Ändern der Hintergrundfarbe von JLabels AWT, Swing, JavaFX & SWT 3
W Swing Performance bei Griderstellung verbessern AWT, Swing, JavaFX & SWT 15
C Pixel-Rendering/Animation Performance in BufferedImage AWT, Swing, JavaFX & SWT 1
I JavaFX Graphics Performance AWT, Swing, JavaFX & SWT 2
S Swing Performance bei Verschachtelung problematisch AWT, Swing, JavaFX & SWT 0
R Performance Drag and Drop & Timer AWT, Swing, JavaFX & SWT 3
O AWT Performance und Bug behebung[brauche Hilfe] AWT, Swing, JavaFX & SWT 2
S Swing Lauftext Performance Probleme, in größerer Anwendung AWT, Swing, JavaFX & SWT 6
B Performance-Probleme AWT, Swing, JavaFX & SWT 17
D DefaultTableCellRenderer - Performance AWT, Swing, JavaFX & SWT 3
hdi Swing [Umfrage] Swing Performance AWT, Swing, JavaFX & SWT 27
B 2D-Grafik BufferedImage Performance AWT, Swing, JavaFX & SWT 3
Hausmeister JTable mit Bildern - Performance AWT, Swing, JavaFX & SWT 5
J JTree Performance AWT, Swing, JavaFX & SWT 2
Developer_X Swing Graphics2D translate zerstört performance AWT, Swing, JavaFX & SWT 2
hdi Swing JTable: Mein CellRenderer ist ein Performance-Killer? AWT, Swing, JavaFX & SWT 7
J Performance bei mouseMoved(...) AWT, Swing, JavaFX & SWT 4
L JFreeChart - Performance bei PNG-Erstellung AWT, Swing, JavaFX & SWT 5
P seltsame Performance Probleme bei 2 Guis abhängig vom Aufruf AWT, Swing, JavaFX & SWT 8
G Performance beim Zeichnen erhöhen? AWT, Swing, JavaFX & SWT 21
hdi bitte um performance ratschläge AWT, Swing, JavaFX & SWT 31
G performance fragen zu AWT, Swing AWT, Swing, JavaFX & SWT 14
T (Java 6) Thumbnails in JFileChooser - Performance steigern? AWT, Swing, JavaFX & SWT 3
hdi schlechte performance bei simplem swing AWT, Swing, JavaFX & SWT 9
G Probleme mit Performance bei einer Tabelle AWT, Swing, JavaFX & SWT 16
M Performance SWT ??? AWT, Swing, JavaFX & SWT 8
P SWT: StyledText Performance steigern? AWT, Swing, JavaFX & SWT 2
P SWT Performance : "Text" - Ausgabe beschleunigen ? AWT, Swing, JavaFX & SWT 21
O performance g2d.drawImage() AWT, Swing, JavaFX & SWT 17
D Performance Probleme Jtable AWT, Swing, JavaFX & SWT 4
N Performance (BufferStrategy?) AWT, Swing, JavaFX & SWT 2
O LookAndFeel und Performance AWT, Swing, JavaFX & SWT 7
W Performance verbessern AWT, Swing, JavaFX & SWT 2
S TableCellRenderer, Performance AWT, Swing, JavaFX & SWT 9
G Problem mit der Anzeige von jLabel. Unlesbar wenn der Text geändert wird. AWT, Swing, JavaFX & SWT 28
H 2D-Grafik Problem mit Paint AWT, Swing, JavaFX & SWT 1
S Layout - Problem AWT, Swing, JavaFX & SWT 1
Tassos JavaFX/Problem mit der Maussteuerung in Stackpane AWT, Swing, JavaFX & SWT 7
sserio Java Fx - Problem AWT, Swing, JavaFX & SWT 3
A Problem Spiel auf Panel der GUI zu bringen AWT, Swing, JavaFX & SWT 1
A JavaFX Controller Problem AWT, Swing, JavaFX & SWT 1
TheWhiteShadow JavaFX ListView Problem beim Entfernen von Elementen AWT, Swing, JavaFX & SWT 1
E LayoutManager Welcher Layout-Mix löst mein Problem? AWT, Swing, JavaFX & SWT 3
Umb3rus JavaFX Problem mit PropertyValueFactory: can not read from unreadable property AWT, Swing, JavaFX & SWT 1
T Problem mit paintComponent() AWT, Swing, JavaFX & SWT 17
AmsananKING Java Menü-Problem AWT, Swing, JavaFX & SWT 1
K JavaFX Resizing-Problem beim BorderLayout (Center Component) beim Arbeiten mit mehreren FXMLs AWT, Swing, JavaFX & SWT 2
G Instance OF Problem AWT, Swing, JavaFX & SWT 9
FrittenFritze Ein Problem mit der CSSBox, die Größe wird nicht angepasst AWT, Swing, JavaFX & SWT 5
M Problem mit dem Anzeigen von Frames im Vordergrund AWT, Swing, JavaFX & SWT 5
Badebay Problem mit JButton AWT, Swing, JavaFX & SWT 2
newJavaGeek Grid-Layout problem AWT, Swing, JavaFX & SWT 7
J JavaFX Löschen im Tabelview macht Problem AWT, Swing, JavaFX & SWT 15
JavaTalksToMe JavaFx ExekutorService Problem AWT, Swing, JavaFX & SWT 2
Zrebna Problem bei Eventhandling (Value soll nach jedem erneutem Klick gelöscht werden) AWT, Swing, JavaFX & SWT 4
B Problem mit JavaFX AWT, Swing, JavaFX & SWT 5
J css Problem AWT, Swing, JavaFX & SWT 5
B JavaFX habe mein Problem fett markiert AWT, Swing, JavaFX & SWT 2
A Swing Filter-Problem AWT, Swing, JavaFX & SWT 1
temi JavaFX Problem mit IntelliJ und JavaFx 11 unter XUbuntu AWT, Swing, JavaFX & SWT 3
L Java FX Problem mit Ubuntu 18 und JavaFx AWT, Swing, JavaFX & SWT 27
H JTable TableCellEditor-Problem AWT, Swing, JavaFX & SWT 0
kodela Swing Problem mit Warten-Dialog AWT, Swing, JavaFX & SWT 16
B JavaFx Scene Builder Problem AWT, Swing, JavaFX & SWT 2
B [Problem] Java öffnet Word-Datein nicht AWT, Swing, JavaFX & SWT 14
T DataBinding Problem AWT, Swing, JavaFX & SWT 5
Blender3D Problem mit € Symbol Font Gotham Windows 10 Swing AWT, Swing, JavaFX & SWT 11
T Problem mit JTable Sortierung AWT, Swing, JavaFX & SWT 2
J Problem mit Platfrom run later AWT, Swing, JavaFX & SWT 15
J Problem mit Platfrom run later AWT, Swing, JavaFX & SWT 0
D Swing SwingUtils / Thread Problem AWT, Swing, JavaFX & SWT 3
L JavaFX Problem beim Aufrufen einer Methode AWT, Swing, JavaFX & SWT 5
T Swing Problem mit Datum und FormattedTextField AWT, Swing, JavaFX & SWT 2
S AWT Java print dialog Problem AWT, Swing, JavaFX & SWT 0
olfibits JavaFX Problem mit HTMLEditor AWT, Swing, JavaFX & SWT 0
W SWT hover-background-problem with first column in TreeViewer AWT, Swing, JavaFX & SWT 0
M Problem mit Add JScrollPane AWT, Swing, JavaFX & SWT 25
Mario1409 Swing JTextArea scroll Problem AWT, Swing, JavaFX & SWT 0
N Swing Problem mit loop AWT, Swing, JavaFX & SWT 2
S Swing Problem mit Button und ActionListener AWT, Swing, JavaFX & SWT 5
S Swing & Clean und build Problem AWT, Swing, JavaFX & SWT 12
S JLabel setText() Problem AWT, Swing, JavaFX & SWT 6
I 2D-Grafik Problem beim Ändern der Farbe eine 2d Objekts AWT, Swing, JavaFX & SWT 3
G Swing Splitpane Problem AWT, Swing, JavaFX & SWT 1
F Problem mit der FXML Rectangle Shape AWT, Swing, JavaFX & SWT 2
N JavaFX Stranges Problem mit der Autoscroll-Eigenschaft von Textareas AWT, Swing, JavaFX & SWT 0
E Java FX FXML Problem mit html Scriptausführung AWT, Swing, JavaFX & SWT 2
J JavaFX Intersect Problem mit Shapes AWT, Swing, JavaFX & SWT 10
R JavaFX MediaPlayer AVI-Problem AWT, Swing, JavaFX & SWT 1
M Swing Problem mit ListCellRenderer AWT, Swing, JavaFX & SWT 7
D Problem mit JTable AWT, Swing, JavaFX & SWT 1

Ähnliche Java Themen

Neue Themen


Oben