在 JScrollPane 中附加 JLabel

Appending JLabels in JScrollPane

我正在编写一个聊天应用程序,目前正在开发聊天 window。我已经拥有的是 JTextArea 放入 JScrollPane 填充物 JPanel。通过append()函数写入和接收消息导致在文本区域添加新行。

我想要更改的是摆脱文本区域并在其位置附加 JLabel 组件。每次发送或接收新消息时,都会出现新标签,具体取决于消息的来源。标签应放在右侧(我们)或左侧(第二个用户)。

Swing 甚至可以做到这一点吗?据我所知,需要做的是将新标签放在之前显示的最后一条消息下方的某个常量值 (SEPARATION_CONSTANT)

我希望所有这些看起来像这张图片,每条消息都是一个新标签,这背后的主要原因是用户将能够发送图片。

我的推理是否正确?我是否需要一些 int 值来表示将放置下一条消息的高度(y 线),或者滚动窗格中是否有任何方法可以做到这一点?

检查我的例子。它使用您想要的布局,使用嵌套面板和不同的布局,但主要的是 BoxLayout on Y_AXIS。它每 2 秒添加一个 "new chat" 来演示组件的方向。

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

我在每个标签中使用 <html> 标签,以便 have line wrapping