0

I am writing a chat app and I am currently working on chat window. What I already have is a JTextArea put into a JScrollPane filling JPanel. Writing and receiving messages cause adding new line in the text area by append() function.

What I would like to change is to get rid of the text area and have appending JLabel components in its place. Every time a new message is sent or received, new labels appear, depending on where message comes from. The label should be placed on either right (us) or left (second user).

Is it even possible to do that is Swing? What I understand needs to be done is putting new label some constant value (SEPARATION_CONSTANT) below last previously displayed message.

I would like all of that to look like in this picture, every message is a new label, the main reason behind this is that user will be able to send pictures.

Is my reasoning correct? Would I need some int value representing height (y cord) on which next message will be put, or is there any way in the scroll pane to do that?

Visualisation

Andrew Thompson
  • 163,965
  • 36
  • 203
  • 405
Igor
  • 153
  • 6
  • Just add a JPanel to JScrollPane. Make it use BoxLayout.Y_AXIS, the components you add to it will be automatically placed one under the other. – pafau k. May 21 '20 at 09:58

1 Answers1

3

Check my example. It uses the layout you want, using nested panels and different layouts, but the main one is a BoxLayout on Y_AXIS. It adds a "new chat" every 2 seconds to demonstrate how components will be oriented.

public class LayoutForChat extends JFrame {
    private static final String LOREM_IPSUM = "Lorem Ipsum is simply dummy text of the printing and typesetting industry."
            + " Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown"
            + " printer took a galley of type and scrambled it to make a type specimen book. It has survived"
            + " not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged."
            + " It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,"
            + " and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
    private static final int CHAT_BOX_WIDTH = 150;
    private JPanel boxPanel;

    public LayoutForChat() {
        super("");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        boxPanel = new JPanel();
        boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.Y_AXIS));
        addLeftChat();
        addRightChat();

        JScrollPane scrollPane = new JScrollPane(boxPanel);
        add(scrollPane, BorderLayout.CENTER);

        setMinimumSize(new Dimension(CHAT_BOX_WIDTH + 150, 400));
        setLocationByPlatform(true);
        pack();

        new Timer(2000, e -> {
            boolean right = (int) (Math.random() * 2) == 0;
            if (right)
                addRightChat();
            else
                addLeftChat();

            JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar();
            SwingUtilities.invokeLater(() -> verticalScrollBar.setValue(verticalScrollBar.getMaximum()));
        }).start();
    }

    private void addChat(int flowLayoutAlign, Color borderColor) {
        JPanel panel = new JPanel(new FlowLayout(flowLayoutAlign));
        JLabel label = new JLabel();
        label.setBorder(BorderFactory.createLineBorder(borderColor));
        label.setText("<html><body style='width: " + CHAT_BOX_WIDTH + "px;'>" + loremIpsum());
        panel.add(label);
        boxPanel.add(panel);
        boxPanel.revalidate();
    }

    private void addRightChat() {
        addChat(FlowLayout.TRAILING, Color.red);
    }

    private void addLeftChat() {
        addChat(FlowLayout.LEADING, Color.green);
    }

    private String loremIpsum() {
        return LOREM_IPSUM.substring(0, (int) (Math.random() * LOREM_IPSUM.length()));
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new LayoutForChat().setVisible(true));
    }
}

I use <html> tag in each label in order to have line wrapping.

George Z.
  • 6,024
  • 4
  • 18
  • 33