JScrollPane не изменяет размеры при изменении размера его содержимого - PullRequest
0 голосов
/ 27 апреля 2020

Я делаю чат-сервер и у меня проблемы с дисплеем. У меня есть JPanel внутри JScrollPane. JPanel отображает текст, но когда текст опускается ниже своей нижней границы на экране, JScrollPane не показывает полос прокрутки. Мой код для окна:

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);
    }
}

JPanel, показывающий текст, является chatPanel, а JScrollPane - scrollPanel.

Вот код 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()));
    }
}

1 Ответ

1 голос
/ 27 апреля 2020
 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()));
}

Указанный выше код неверен. Вы не должны пытаться играть с размером компонента.

Полосы прокрутки появятся автоматически, когда «предпочтительный размер» компонентов превышает размер области прокрутки.

Поэтому вы должны переопределить метод getPreferredSize() вашего компонента. Поэтому ваш код должен выглядеть примерно так:

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);
}

Значение "width" должно быть параметром, который вы передаете своему классу, чтобы предложить ширину компонента по умолчанию.

Кроме того, вы рисуете заново изобретать колесо. JPanel перекрасит свой фон. Таким образом, код должен быть:

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

И тогда вы вызовете:

setBackground( Color.WHITE );

в своем конструкторе.

...