JTextArea Cursor Position soll nach append bleiben wo sie ist

Hi,

ich habe eine JTextArea. Wenn ein Button gedrückt wird, wird der String “test” in die JTextArea geschrieben, mittels append.
Die JTextArea ist in einer JScrollPane eingebettet.
Wenn die JTextArea voll ist kann man mit den Scrollbalken hin und her scrollen.

Ich möchte, dass nach Einfügen des Strings die Position des Cursors gleichbleibt. Momentan springt mir der Cursor immer
an die unterste Position der JTextArea, so dass der zuletzt eingefügte String zu sehen ist.

Was muss ich ändern damit nach append, die Cursors Position da bleibt wo er ist. Er soll mir nicht nach unten springen.

public class MyFrame extends JFrame
{
	private final static String LINESEPARATOR = System.getProperty("line.separator");
	private JTextArea textArea;
	
	public MyFrame()
	{
		this.setSize(400, 300);
		this.setLocationRelativeTo(null);
		this.setTitle("Client GUI");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		this.textArea = new JTextArea();
		this.textArea.setEditable(false);
		this.textArea.setLineWrap(true);
		this.textArea.setWrapStyleWord(true);
		JScrollPane scrollPane = new JScrollPane(this.textArea);
	        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		JButton button = new JButton("test");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent ae) 
			{
				textArea.append("test" + LINESEPARATOR);
			}	
		});
		
		this.add(scrollPane, "Center");
		this.add(button, "South");
		
		this.setVisible(true);
	}
}

Du koenntest dir bevor du append aufrufst mit JtextArea.getCaretPosition die position abfragen und nach dem du append aufgerufen hast mit setCaretPosition wieder an diese stelle setzten

Die Einfügungsmarke (Caret) ist standardmäßig am Ende des Textes in der TextArea, wenn du per append was anhängst, wandert das Caret automatisch wieder ans Ende.

Entweder holst dir vorneweg die Caret Position (int) und haust die nach append wieder rein (wie AmunRa schon sagte), damit wird der Text in der Area aber mitunter rumspringen, oder du startest deine GUI mit einer definierten Caret Position (z.B. .setCaretPosition(0)). Append geht dann immernoch ans Ende, Caret bleibt aber wo es war.

Seit Java 1.5 gibt es die Möglichkeit das Verhalten über per Policy zu beinflussen.

Folgendes z.B. lässt die Caret Postion unverändert:

caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);```

Danke für die Antworten

Ist vllt nur ne kleine Sache, aber je nachdem was du vorhast, rate ich dir statt ner JTextArea eine Jlist zu verwenden.
Die is dafür gedacht Einträge zeilenweise anzuzeigen und später hast du s dann n bisschen einfacher wenns draum geht Einträge zu markieren, editieren, löschen etc. oder einfach nur n Mausklick auf nem Eintrag zu erkennen

Für mein Vorhaben benötige ich eine JTextArea, da ich damit einen Chatverlauf darstellen möchte. Bei einem Button Klick öffnet sich die Historie des Chatverlaufs.
Falls dabei gerade eine neue Nachricht reinkommt wird sie ebenfalls sofort in der Historie angezeigt. Über eine JCheckBox kann der Benutzer sagen
ob sofort nach unten zur neu ankommenden Nachricht gepsrungen werden soll oder nicht. Falls der Benutzer nämlich gerade nach einem bestimmten Eintrag sucht o.ä. wäre es störend wenn hinuntergesprungen werden würde. Der Benutzer hat also die Wahl mittels der JCheckBox.

Ich habe jetzt die setUpdatePolicy Variante versucht.
Wird die JCheckBox markiert so wird folgender Code ausgeführt:

DefaultCaret caret = (DefaultCaret) textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAY_UPDATE);

Wird die Markierung der JCheckBox aufgehoben wird dieser Code ausgeführt:

DefaultCaret caret = (DefaultCaret) textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);

Nachdem einmal setUpdatePolicy jedoch aufgerufen wurde, lässt sie sich aber scheinbar nicht nochmal ändern.
Ist es über diesen Weg nicht möglich dynamisch einzustellen, ob das Caret runterspringen soll beim Eintreffen einer neuen Nachricht oder an
der Position bleiben soll wo es war?

Weils so ist wie ich gesagt habe, ist die Einfügungsmarke nicht am Ende des Textes, springt die auch nicht mit, egal ob Update an oder aus ist. Du kannst mit der UpdatePolicy verhindern, dass die Caret die Position ändert, egal wo die ist, aber wenn die immer am Ende des Textes sein soll, muss sie dahin auch händisch hinbewegen.

Chatverlauf heißt der Cursor interessiert Dich gar nicht und ist ohnehin nicht sichtbar?
Eine Variante die ich favorisieren würde:
Die UpdatePolicy steht fest auf NEVER. Wenn neuer Text angehängt wurde nutzt Du in Abhängigkeit des Status der Checkbox die scrollRectToVisible(Rectangle) um zum neu eingefügten Inhalt zu scrollen.

Danke für die Hinweise