[AWT] TextArea Hack automatisch ans Ende scrollen

Thomas Darimont

Erfahrenes Mitglied
[AWT] TextArea Hack automatsich ans Ende scrollen

Hallo!

Da ich mich heute ca. 4 Stunden mit einem Problem der java.awt.TextArea herumschlagen musste, für das es so im Internet (IMHO) KEINE Lösung gab (weder in den Sun Developer Foren, noch in Java News Groups, bzw. hab ich dort zumindest keine zu dem Problem gefunden die funktioniert).

Also:

Das Problem ist folgendes:

Über einen Button-Klick soll der in einem TextField enthaltene Text in eine TextArea gebracht werden. Die TextArea ist so konfiguriert, dass sie nur eine bestimmte Anzahl von Spalten besitzt und die Zeilen somit ab einer gewissen Länge umgebrochen werden. Es wird nur eine vertikale Scrollbar angezeigt. Wenn jetzt nun ein Text in die TextArea eingefügt werden soll, so soll die ScrollBar automatisch nach unten Scrollen, so dass immer der zuletzt hinzugefügte Text sichtbar ist.

Das Problem ist nur, dass die trivialen Lösungen mit:

Code:
TextArea  ta = new TextArea("", 10, 25, TextArea.SCROLLBARS_VERTICAL_ONLY);

...

for(int i = 0: i < 100; i++){
    ta.setText("BLA neuer Text" + i);
}

//Dies hier wird immer in den Java Newsgroups/Foren als Lösung angegeben aber das funktioniert nicht ...

ta.setCaretPosition(ta.getText().length());
...

... nicht bei der java.AWT.TextArea funktionieren....

Die Lösung des Rätsels gestalltet sich nun wie folgt:

Code:
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Component;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

/*
 * Created on 19.06.2004
 *
 */

/**
 * @author Administrator
 * 19.06.2004
 **/
public class TextAreaHack extends Applet {

	/* Panel mit Button und textField */
	private final Panel ctlPanel;
	/* Unser Sorgenkind die TextArea */
	private final TextArea textArea;
	/* Das TextField */
	private final TextField textField;
	/* Der Button */
	private final Button btnSubmit;

	public TextAreaHack () {

		/*
		 * Die TextArea wird mit 10 Zeilen und 25 Spalten und nur einer
		 * VertikalenScrollbar initialisiert 
		 */
		textArea = new TextArea("", 10, 25, TextArea.SCROLLBARS_VERTICAL_ONLY);
		// Die textArea ist read-only
		textArea.setEditable(false);

		ctlPanel = new Panel();

		ctlPanel.setLayout(null);

		textField = new TextField();

		btnSubmit = new Button("send");

		//Wir hängen dem Button einen MouseListener an
		btnSubmit.addMouseListener(final new MouseAdapter() {
			public void mousePressed(final MouseEvent evt) {
				//Hier hängen wir den Text an die TextArea
				textArea.append(textField.getText() + "\n");

				/*
				 * Hier kommt der Trick!
				 * Wir fangen uns das MouseEvent das für den Button generiert wurde auf,
				 * und bauen uns aus seinen Eigenschaften ein eigenes MouseEvent zusammen
				 */

					final MouseEvent e =
						new MouseEvent(
							(Component) evt.getSource(),
							evt.getID(),
							evt.getWhen(),
							evt.getModifiers(),
							100, //Hier hab ich die Mouse-Click (X) Position geändert
							100, //Hier hab ich die Mouse-Click (Y) Position geändert
							evt.getClickCount(), evt.isPopupTrigger());

				/* 
				 * Dieses "modifizierte" Event schicken wir wieder an die TextArea wobei
				 * diese das Event verarbeitet und so tut als hätten wir nach dem
				 * Button direkt auf sie geklickt ..... und das default Verhalten der
				 * TextArea sagt nun "ok ich habe einen Mouse-Klick empfangen
				 * ich scrolle mal zum Boden!"
				 * 
				 */
				textArea.dispatchEvent(evt);
				/*
				 * Ein unschöner Nebeneffekt von der Sache ist, dass durch den 
				 * simulierten Klick ein das oberste Zeichen blau markiert wird.
				 * Um dies zu vermeiden selektieren wird direkt nach dem abfeuern des Events
				 * das Ende des Textinhalts der TextArea (von Ende bis Ende ) also 0 Zeichen   
				 */
				final int len = textArea.getText().length();
				textArea.select(len, len);

			}
		});
		ctlPanel.setSize(200, 25);
		ctlPanel.add(textField);
		textField.setBounds(0, 0, 170, 18);
		ctlPanel.add(btnSubmit);
		btnSubmit.setBounds(170, 0, 30, 18);
	}

	public void init() {
		add(textArea, BorderLayout.CENTER);
		add(ctlPanel, BorderLayout.SOUTH);
	}
}

Jemand ne andere Lösung auf Lager?

Gruß Tom
 
Zuletzt bearbeitet:
Zurück