Thibault
Thibault

Reputation: 13

JScrollPane not resizing when I resize its content

I am doing a chat server and I'm having trouble with the display. I have a JPanel inside a JScrollPane. The JPanel displays the text, but when the text goes lower than its lower border on the screen, the JScrollPane doesn't show any scroll bars. My code for the window :

package com.main;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.util.ArrayList;

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

import com.panels.ChatPanel;
import com.panels.LinePanel;

public class Window extends JFrame
{
    private ChatPanel chatPanel;

    private JPanel content;

    private TextField textField;

    private ArrayList<LinePanel> linePanels = new ArrayList<LinePanel> ();

    private Font font = new Font("Arial", Font.BOLD, 17);

    private JScrollPane scrollPanel;

    public Window(TextField textField)
    {
        //Sets the title of the window
        this.setTitle("Chat");
        //Sets the size of the window
        this.setSize(1000, 800);
        //Sets the location of the window on the screen
        this.setLocation(50, 0);
        //The program will close when the red X is pressed
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.chatPanel = new ChatPanel();

        this.content = new JPanel();

        this.scrollPanel = new JScrollPane(this.chatPanel);
        this.scrollPanel.getVerticalScrollBar().setUnitIncrement(16);
        this.scrollPanel.setBorder(BorderFactory.createEmptyBorder());

        this.textField = textField;
        this.textField.setPreferredSize(new Dimension(this.getWidth(), 30));
        this.textField.setFont(this.font);

        //Sets the content panel
        this.setContentPane(content);
        this.setLayout(new BorderLayout());

        this.content.add(this.scrollPanel, BorderLayout.CENTER);
        this.content.add(this.textField, BorderLayout.SOUTH);
        this.content.setBackground(Color.white);

        //Makes the window visible
        this.setVisible(true);
    }

    public void screen()
    {
        this.chatPanel.repaint();

        this.scrollPanel.repaint();
        this.scrollPanel.revalidate();

        this.getContentPane().repaint();
        this.revalidate();
    }

    public void addLine(String newLine)
    {
        this.chatPanel.addLine(newLine);
    }
}

The JPanel showing the text is chatPanel and the JScrollPane is scrollPanel.

Here is the code of chatPanel :

package com.panels;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.ArrayList;

import javax.swing.JPanel;

public class ChatPanel extends JPanel
{
    private ArrayList<LinePanel> linePanels = new ArrayList<LinePanel> ();

    private ArrayList<String> chat = new ArrayList<String> ();

    private GridLayout layout = new GridLayout(1, 1);

    private static final int LINE_HEIGHT = 25;

    public ChatPanel()
    {
        super();

        this.setLayout(layout);
    }

    public void paintComponent(Graphics g)
    {

        g.setColor(Color.white);
        g.fillRect(0,  0, this.getWidth(), this.getHeight());

        g.setFont(new Font("Arial", Font.BOLD, 20));
        g.setColor(Color.black);

        for (int i = 0; i < this.chat.size(); i ++)
            g.drawString(this.chat.get(i), 10,  (i + 1) * LINE_HEIGHT);
    }

    public void addLine(String newLine)
    {
        this.chat.add(newLine);

        if (this.getHeight() < this.chat.size() * LINE_HEIGHT)
            this.setSize(new Dimension(this.chat.size() * LINE_HEIGHT, this.getWidth()));
    }
}

Upvotes: 1

Views: 93

Answers (1)

camickr
camickr

Reputation: 324197

 public void addLine(String newLine)
{
    this.chat.add(newLine);

    if (this.getHeight() < this.chat.size() * LINE_HEIGHT)
        this.setSize(new Dimension(this.chat.size() * LINE_HEIGHT, this.getWidth()));
}

The above code is incorrect. You should not be attempting to play with the size of the component.

The scrollbars will appear automatically when the "preferred size" of the components is greater than the size of the scroll pane.

Therefore you should be overriding the getPreferredSize() method of your component. So your code should be something like:

public void addLine(String newLine)
{
    this.chat.add(newLine);

    revalidate();
    repaint();
}

@Override
public void getPreferredSize()
{
    int height = chat.size() * LINE_HEIGHT;
    return new Dimension(100, height);
}

The "width" value should be a parameter that you pass to your class to suggest a default width for the component.

Also, you painting is reinventing the wheel. A JPanel will repaint its background. So the code should be:

//g.setColor(Color.white);
//g.fillRect(0,  0, this.getWidth(), this.getHeight());
super.paintComponent(g);

And then you would invoke:

setBackground( Color.WHITE );

in your constructor.

Upvotes: 2

Related Questions