UpdatePolicy wird nicht richtig gesetzt / funktioniert nicht

Hallo miteinander,

ich habe bereits seit längerem das folgende Problem und habe bereits in einem anderem Forum nach einer Lösung gefragt. Nun versuche ich hier mein Glück.

Ich programmiere aktuell ein Chat-System um meine Fähigkeiten zu stärken. Dazu habe ich ein kleines GUI mit ScrollPane. Dieses ScrollPane soll bei jeder neuer Nachricht automatisch nach unten scrollen. Wenn ich aber eine alte Nachricht lesen möchte, soll dieses dies erkennen und bei einer neuen Nachricht nicht nach unten scrollen. Sobald ich wieder nach unten scrolle, soll bei jeder neuen Nachricht wieder nach unten gescrollt werden. Dafür dachte ich an die UpdatePolicy.

Funktionen:

  • Bei jeder neuen Nachricht wird automatisch nach unten gescrollt [check]
  • Nach oben scrollen, nach unten scrollen und bei jeder neuen Nachricht wird automatisch nach unten gescrollt [check]
  • Nach oben scrollen und bei jeder neuen Nachricht soll nicht automatisch nach unten gescrollt werden [check]
  • Nach oben scrollen, eine neue Nachricht bekommen, nach unten scrollen und wieder eine neue Nachricht bekommen, dabei automatisch nach unten scrollen [ ] (dort tritt beim automatischen nach unten scrollen das Problem auf)

Per Abfragen habe ich das setzen der UpdatePolicy abgefragt, diese scheinen aber zu funktionieren.

Desshalb habe ich ein kleines Programm ohne ScrollListener erstellt, um die grundsätzliche Funktion zu testen. Dieses habe ich mit SourceCode angehängt:

Nach dem starten ist es möglich mit der Eingabe von “on” und “off” die UpdatePolicy zu ändern, mit “get” kann der aktuelle Status der UpdatePolicy abgefragt werden. Jede andere Eingabe wird als Text erkannt und ausgegeben, um eine neue Nachricht zu erzeugen. Damit kann man dann das Problem darstellen. Ich erkläre und zeige das Problem auch gerne direkt, falls dies ein wenig unverständlich ist.

Ich freue mich auf einen Lösungsvorschlag.

Grüße Henne

Ich erhalte weder hier, noch in anderen Foren eine Antwort auf dieses Thema.
Ich hoffe inzwischen aber auch in keinem Forum mehr auf eine Antwort.
Auch hier haben gerade mal 2 Leute meine angehängten Dateien angeschaut.
Ich frage mich wirklich, ob ich der erste bin, der UpdatePolicy nutzen möchte. Naja, auch egal.

Ich wünsche allen anderen noch viel Spaß an Java und verabschiede mich auch schon wieder aus diesem Forum.

habe das Programm ausprobiert,
scheint alles zu funktionieren, aber Bedienung nicht ganz leicht,

nur nach oben scrollen deaktiviert das Verhalten des Springens ans Ende nicht (bei mir),
man muss auch irgendwo hinklicken, so dass die CaretPosition nicht mehr die letzte ist, dann bleibt es dort,

um das Mitscrollen wieder zu aktivieren muss man die CaretPosition ganz ans Ende bekommen,
irgendwo hinter der letzten Nachricht klicken

immerhin geht auch ein Befehl wie
chatO.setCaretPosition(chatO.getText().length());
vielleicht kannst du das bei ScrollListenern nutzen, programmatisch den Modus wieder einschalten


ein Titel ohne Abgewöhn-Begriff ‚Policy‘, sondern simpel ‚Scroll in JTextArea‘ oder so hätte vielleicht früher mehr angelockt, also z.B. mich :wink:

Was hat denn die Caret Update Policy mit dem Scrollen zu tun? Ganz vordergründig:

** Bei jeder neuen Nachricht wird automatisch nach unten gescrollt [check]**

Bei mir schonmal nicht.

Wenn es nur um das scrollen geht, bzw. darum, die Scrollbar “unten einrasten” zu lassen, dann hätte ich das irgendwie pragmatisch gelöst…

etwa so…
[spoiler]

…aber leider liest der Autor das aber nicht mehr :o)

package bytewelt.updatepolicy;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JViewport;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.DefaultCaret;

public class GUI extends JFrame
{	
	private static final long serialVersionUID = 42L;
	public JFrame window = new JFrame();
	
	public ArrayList<KeyEvent> keys = new ArrayList<KeyEvent>();
	
	// Komponenten
	private JTextArea chatO;
	public DefaultCaret caretO; 
	public JScrollPane scrollO;
	private JTextArea chatI;
	private JScrollPane scrollI;
	private JTextArea clientL;
	private JScrollPane scrollC;
	private JButton button;
	
	private boolean autoScrollToEnd = true;
	
	public void output()
	{
		JPanel panel = new JPanel();
		panel.setLayout(new GroupLayout(panel));
		window.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		window.setSize(800, 400);
		window.setLocation(200, 400);
		window.setTitle("ChickenChat V1.1.6a");
		panel.setBackground(Color.GRAY);
		
		panel.add(chatOutput());
		panel.add(chatInput());
		panel.add(clientList());
		panel.add(buttonAbschicken());
		
		window.setResizable(false);
		window.add(panel);
		window.setVisible(true);
	}
	
	public Component chatOutput()
	{
	    chatO = new JTextArea();
	    
	    chatO.getDocument().addDocumentListener(new DocumentListener()
        {
            @Override
            public void removeUpdate(DocumentEvent e)
            {
                if (autoScrollToEnd)
                {
                    chatO.setCaretPosition(chatO.getText().length());
                }
            }
            
            @Override
            public void insertUpdate(DocumentEvent e)
            {
                if (autoScrollToEnd)
                {
                    chatO.setCaretPosition(chatO.getText().length());
                }
            }
            
            @Override
            public void changedUpdate(DocumentEvent e)
            {
                if (autoScrollToEnd)
                {
                    chatO.setCaretPosition(chatO.getText().length());
                }
            }
        });
	    
//	    chatO.setText(
//                "0
"+
//                "1
"+
//                "2
"+
//                "3
"+
//                "4
"+
//                "5
"+
//                "6
"+
//                "7
"+
//                "8
"+
//                "9
"+
//                "10
"+
//                "11
"+
//                "12
"+
//                "13
"+
//                "14
"+
//                "15
"+
//                "16
"+
//                "17
"+
//                "18
"
//	    );
	    
		chatO.setLineWrap(true);
		chatO.setEditable(false);
		caretO = (DefaultCaret) chatO.getCaret();
		caretO.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
		scrollO = new JScrollPane(chatO);
		scrollO.setSize(550, 290);
		scrollO.setLocation(10, 10);
		scrollO.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
		scrollO.getVerticalScrollBar().setUnitIncrement(5);
		
		JScrollBar verticalScrollBar = scrollO.getVerticalScrollBar();
		verticalScrollBar.addAdjustmentListener(new AdjustmentListener()
        {
            @Override
            public void adjustmentValueChanged(AdjustmentEvent e)
            {
                int vis = verticalScrollBar.getVisibleAmount();
                int val = verticalScrollBar.getValue();
                autoScrollToEnd = vis + val == verticalScrollBar.getMaximum();
                //System.out.println("autoScrollToEnd? "+autoScrollToEnd);
            }
        });
		
		return scrollO;
	}
	
	public Component chatInput()
	{
		chatI = new JTextArea();
		chatI.setLineWrap(true);
		chatI.addKeyListener(new KeyL());
		scrollI = new JScrollPane(chatI);
		scrollI.setSize(550, 54);
		scrollI.setLocation(10, 310);
		scrollI.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
		
		return scrollI;
	}
	
	public Component clientList()
	{
		clientL = new JTextArea();
		clientL.setAutoscrolls(true);
		clientL.setEditable(false);
		scrollC = new JScrollPane(clientL);
		scrollC.setSize(213, 290);
		scrollC.setLocation(570, 10);
		scrollC.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
		scrollC.getVerticalScrollBar().setUnitIncrement(5);
		return scrollC;
	}
	
	private Component buttonAbschicken()
	{
		button = new JButton("Abschicken");
		
		button.addActionListener(new ActionListener()
		{
			 public void actionPerformed(ActionEvent e)
			 {
				 test(getChatInput());
				 delChatInput();
			 }
		});
		
		button.setSize(213, 54);
		button.setLocation(570, 310);
		return button;
	}
	
	public void test(String msg)
	{
		if(msg.equalsIgnoreCase("exit"))
		{
			System.exit(0);
		}
		else if(msg.equalsIgnoreCase("on"))
		{
			caretO.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
			addClientList(caretO.getUpdatePolicy()+"");
		}
		else if(msg.equalsIgnoreCase("off"))
		{
			caretO.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
			addClientList(caretO.getUpdatePolicy()+"");
		}
		else if(msg.equalsIgnoreCase("get"))
		{
			addClientList(caretO.getUpdatePolicy()+"");
		}
		else
		{
			addChatOutput(msg);
		}
	}
	
	// Get
	public String getChatOutput()
	{
		return chatO.getText();
	}
	
	public String getChatInput()
	{
		return chatI.getText();
	}
	
	public String getClientList()
	{
		return clientL.getText();
	}
	
	public JViewport getScrollOutput()
	{
		return scrollO.getViewport();
	}
	
	// Set
	public void setChatOutput(String text)
	{
		chatO.setText(text);
	}
	
	public void setChatInput(String text)
	{
		chatI.setText(text);
	}
	
	public void setClientList(String text)
	{
		clientL.setText(text);
	}
	
	// Del
	public void delChatOutput()
	{
		chatO.setText("");
	}
	
	public void delChatInput()
	{
		chatI.setText("");
	}
	
	public void delClientList()
	{
		clientL.setText("");
	}
	
	// Add
	public void addChatOutput(String text)
	{
		String inhalt = chatO.getText();
		if(inhalt.equalsIgnoreCase(""))
		{
			chatO.setText(text);
		}
		else
		{
			chatO.append("
"+text);
		}
	}
	
	public void addChatInput(String text)
	{
		chatI.append(" "+text);
	}
	
	public void addClientList(String text)
	{
		String inhalt = clientL.getText();
		if(inhalt.equalsIgnoreCase(""))
		{
			clientL.setText(text);
		}
		else
		{
			clientL.append("
"+text);
		}
	}
	
	public void addChatInputNextLine()
	{
		chatI.append("
");
	}
}

[/spoiler]