1

i have problem with my JTextArea i java. When i print output in the text area, it doesn't automatically scroll to the bottom. And when it reaches the bottom of text area i cannot scroll it with scroll panel. Here is my GUI Code:

public void initializeWindow()
    {
        JPanel pan;
        JPanel colorBox;
        JPanel consolePanel;
        JLabel panText;
        JFrame frame = new JFrame();
        JScrollPane scroll;


        gridPanels = new JPanel[sizeX][sizeY];
        boardPanel = new JPanel();
        legend = new JPanel();
        consolePanel = new JPanel();
        consoleOutput = new JTextArea(25,20);


        consoleOutput.setEditable(false);
        consoleOutput.setPreferredSize(new Dimension( 200,300));
        consoleOutput.setAutoscrolls(true);

        scroll = new JScrollPane(this.consoleOutput, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        consolePanel.setBorder(BorderFactory.createLineBorder(Color.black));
        consolePanel.add(consoleOutput);
        consolePanel.add(scroll);


        boardPanel.setBorder(BorderFactory.createEmptyBorder(30,30,10,30));
        boardPanel.setLayout(new GridLayout(sizeX,sizeY));

        legend.setBorder(BorderFactory.createEmptyBorder(30,30,10,30));
        legend.setPreferredSize( new Dimension(300,boardPanel.getHeight()));


        PrintStream printStream = new PrintStream(new CustomOutputStream(consoleOutput));


        for (Organizm org: legendOrgs)
        {
            pan = new JPanel();
            colorBox = new JPanel();
            panText = new JLabel();

            pan.setMaximumSize(new Dimension(100,70));
            pan.setAlignmentX(Component.LEFT_ALIGNMENT);
            pan.setLayout(new FlowLayout(FlowLayout.LEADING));

            colorBox.setBackground(org.getOrgColor());
            colorBox.setAlignmentX(Component.LEFT_ALIGNMENT);
            colorBox.setPreferredSize(new Dimension(30,30));
            colorBox.setMaximumSize(new Dimension(30,30));

            panText.setPreferredSize(new Dimension(100,15));
            panText.setText(" - " + org.getName());
            panText.setAlignmentX(Component.RIGHT_ALIGNMENT);

            pan.add(colorBox);
            pan.add(panText);

            legend.add(pan);
        }
        legend.add(consolePanel);

        for(int i=0; i<sizeY; i++)
        {
            for(int j=0; j<sizeX; j++)
            {
                gridPanels[i][j] = new JPanel();
                if(organizmy[i][j]!=null)
                    gridPanels[i][j].setBackground(organizmy[i][j].getOrgColor());
                else gridPanels[i][j].setBackground(Color.white);
                boardPanel.add(gridPanels[i][j]);
            }
        }

        System.setOut(printStream);
        System.setErr(printStream);
        frame.add(boardPanel);
        frame.add(legend,BorderLayout.EAST);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("Wirtualny świat");
        frame.pack();
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
        worldFrame = frame;
    }

And here is my Custom output Stream class which is used to print everything i print via System.out.println to my text Area:

public class CustomOutputStream extends OutputStream
{
    private final JTextArea textArea;

    public CustomOutputStream(JTextArea textArea)
    {
        this.textArea = textArea;
    }

    @Override
    public void write(int b)
    {
        textArea.append(String.valueOf((char)b));
        textArea.setCaretPosition(textArea.getDocument().getLength());
    }




}

Here is link to image what it looks like in GUI:

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
XYZEK 0
  • 13
  • 1
  • 2
  • 1
    Swing components should be updated on the EDT. – camickr May 26 '21 at 21:16
  • You mean something like [this for example](https://stackoverflow.com/questions/12945537/how-to-set-output-stream-to-textarea/12945678#12945678) – MadProgrammer May 26 '21 at 21:50
  • A component can have only one parent at a time. Remove `consolePanel.add(consoleOutput);` completely; that line is removing your JTextArea from the JScrollPane and designating consolePanel as the JTextArea’s new parent. – VGR May 27 '21 at 01:32
  • Hmm, I removed consolePanel.add(consoleOutput); as VGR advised, but my text still dont move. I have suspicion that text is not even addded to TextArea After area is filled up with text. And i dont really know what update on EDT means, could you explain? – XYZEK 0 May 27 '21 at 10:46
  • The EDT is the "Event Dispatch Thread" anytime you modify a swing component you should use [SwingUtilities.invokeLater](https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)) that way the changes are made on the EDT. – matt May 27 '21 at 11:41

2 Answers2

1

You need to remove this line from your code:

consoleOutput.setPreferredSize(new Dimension( 200,300));

Unfortunately, it prevents your JTextArea from being scrollable because you set static size to that element.

P.S. Stay away from Swing - there are better options in Java

Czumpi
  • 26
  • 2
0

It works for me.

import javax.swing.*;
public class Scrollin{

    public static void main(String[] args){
        JFrame frame = new JFrame("scrolling");
        JTextArea area = new JTextArea(20, 20);
        
        frame.add(new JScrollPane(area));
        frame.setVisible(true);
        frame.pack();
        Timer t = new Timer( 150, evt->{
            area.setCaretPosition( area.getDocument().getLength() );
            area.append("word is born\n");
        });
        t.start();
    }
}

As text is added, the window will scroll to the end provided the cursor is at the end of the document.

Maybe you can start with something as short as this to demonstrate your issue?

matt
  • 10,892
  • 3
  • 22
  • 34
  • Thanks for your reply, il give it a check and write my feedback soon :). – XYZEK 0 May 26 '21 at 20:24
  • Hmm, so you are adding Scroll pane directly to frame. I wrapped it inside Another Panel, maby that is the problem? Does ScrollPane need to be loosely added to frame to work properly? – XYZEK 0 May 27 '21 at 11:08
  • @XYZEK0 I don't know what "loosely added" means. It really shouldn't matter what component the JScrollPane is in, if they're setup properly it should function ok. I think you should switch the order of your `setCaretPosition` and `append` calls. If the cursor is at the end of the document it will stay there. – matt May 27 '21 at 11:30