# JScrollPane Autoscroll



## ViktorW (5. Aug 2010)

Hallo,

ich habe ein JPanel, welches einem JScrollPane geadded wird.
Das JPanel dient als Ausgabefläche eines Chats. Die Nachrichten werden über zur Laufzeit erzeugte JLabels hinzugefügt.

Ich würde mein JScrollPane nun gerne so einstellen, dass es automatisch mit scrollt sobald neue Nachrichten eingehen, jedoch nur, wenn der Scrollbalken nicht gerade manuell benutzt wird. Schließlich soll der Benutzer in der Lage sein, seinen Chatverlauf durchzuschauen, ohne das der Balken bei jeder neuen Nachricht wieder nach unten springt.

Meine derzeitige Lösung scrollt zwar automatisch, lässt sich jedoch gar nicht mehr manuell bedienen:

```
// Autoscroll to bottom ...
  scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
    public void adjustmentValueChanged(AdjustmentEvent e) {  
      e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
    }
  });
```

Im Prinzip würde mir schon jeder bessere Ansatz helfen...
Wichtig ist jedoch, das ich ein JPanel als Basis fürs JScrollPane benutze! Keine TextArea oder Ähnliches.

Danke im Voraus!


----------



## Flown (5. Aug 2010)

Ein Denkanstoß:

Wenn eine neue Nachricht kommt, dann würd ich ein Event auslösen, der dann die Scrollbar ganz nach unten setzt. So quasi ein MessageRecievedListener


----------



## ViktorW (5. Aug 2010)

Flown hat gesagt.:


> Ein Denkanstoß:
> 
> Wenn eine neue Nachricht kommt, dann würd ich ein Event auslösen, der dann die Scrollbar ganz nach unten setzt. So quasi ein MessageRecievedListener



Ich habe ähnliche Varianten bereits getestet, der User sollte jedoch in der Lage bleiben, seinen Verlauf durchschauen zu können ohne dabei bei jeder eingehenden Nachricht wieder and Ende des Panels geworfen zu werden.
Viele Messenger funktionieren nach diesem Prinzip... gibt es eine Möglichkeit die Position des Scrollbalkens abzufragen und besagtes Event einfach immer dann auszulösen, wenn dieser sich ganz unten befindet..?


----------



## Flown (5. Aug 2010)

Hmm du könnest einen Button machen der die Scrollbar ganz nach unten springen lässt, wenn er gedrückt wurde bleibt die Scrollbar jedes mal ganz unten, wenn der User dann nach oben scrollt, dann bleibt die Scrollbar wo sie ist, bist du wieder auf den besagten Button klickst, oder ganz nach unten scrollst.


----------



## ProgX (5. Aug 2010)

Es gibt bestimmt eine Funktion die dir sagt an welcher Position du dich gerade mit der Scrollbar befindest!
Diese nimmst du dann her, wenn du ganz unten bist machst du den Autoscroll und wenn nicht, bleibst du dort wo du dich gerade befindest.


----------



## Michael... (5. Aug 2010)

Zu nächst einmal möchte ich nochmal erwähnen, dass ich das Einfügen neuer JLabels nicht gut heissen kann ;-) (das könnte man sicherlich auch mit einer JList hinbekommen)

Zu der eigentlichen Frage:
Meinst sowas wie in folgendem Code?
Solange der Scrollbalken per Maus gehalten wird bleibt die Position erst, wenn er wieder losgelassen wird, wird beim einfügen einer neuen "Nachricht" nach unten gescrollt.

```
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class AutoScrollDemo extends JFrame implements Runnable{
	private JPanel panel;
	private JScrollPane scroll;
	
	public AutoScrollDemo() {
		panel = new JPanel();
		panel.setPreferredSize(new Dimension(300, 300));
		this.getContentPane().add(scroll = new JScrollPane(panel));
	}
	
	public void increasePanelSize() {
		Dimension d = panel.getPreferredSize();
		d.height +=100;
		panel.setPreferredSize(d);
		scroll.validate();
		scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getMaximum());
	}
	
	//Um die Vergrösserung bei Nachrichteneingang zu simulieren
	public void run() {
		Dimension d;
		while(true) {
			try {
				Thread.sleep(2000);
				this.increasePanelSize();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		AutoScrollDemo demo = new AutoScrollDemo();
		demo.setBounds(0, 0, 200, 200);
		demo.setLocationRelativeTo(null);
		demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		demo.setVisible(true);
		new Thread(demo).start();
	}
}
```


----------



## ViktorW (5. Aug 2010)

Michael... hat gesagt.:


> ```
> scroll.validate();
> scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getMaximum());
> ```



Heh.. perfekt, genau was ich gesucht habe!


----------

