[最终编辑]

哦,伙计们。
我不知道为什么它不能在我的聊天程序中工作..但是我设法通过现在可滚动的实现修复了sscce..。谢谢你们!
码:

package de.sky.cjat;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.Scrollable;
import javax.swing.UIManager;

public class MyKskb {

    private int row;

    class SomethingPanel extends JPanel implements Scrollable {

        public SomethingPanel(LayoutManager manager){
            super(manager);
        }

        @Override
        public Dimension getPreferredScrollableViewportSize(){
            return getPreferredSize();
        }

        @Override
        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
            return 5;
        }

        @Override
        public boolean getScrollableTracksViewportHeight(){
            return false;
        }

        @Override
        public boolean getScrollableTracksViewportWidth(){
            return true;
        }

        @Override
        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
            return 1;
        }
    }

    public MyKskb(){
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setPreferredSize(new Dimension(800, 600));
//      final JPanel content = new JPanel(new GridBagLayout());
        final SomethingPanel content = new SomethingPanel(new GridBagLayout());

//      final JPanel empty = new JPanel();
//      empty.setPreferredSize(new Dimension(0, 0));
//      GridBagConstraints gbc = new GridBagConstraints();
//      content.add(empty, gbc);
        content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
        content.getActionMap().put("§", new AbstractAction(){
            @Override
            public void actionPerformed(ActionEvent e){
                JPanel p = new JPanel(new BorderLayout());
                p.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
                p.setBackground(Color.GRAY);

                GridBagConstraints gbc = new GridBagConstraints();
                gbc.insets = new Insets(10, 10, 10, 10);
                gbc.weightx = 1.0;
                gbc.gridx = 0;
                gbc.gridy = row++;
                gbc.fill = GridBagConstraints.HORIZONTAL;

//              content.remove(empty);
//              gbc.gridy = row;
//              gbc.weighty = 1.0;
//              content.add(empty, gbc);

                JTextArea text = new JTextArea(
                        Math.random() > 0.5 ?
                        "ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC" :
                        "FFFFFFFFFFFFABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
                text.setLineWrap(true);
                p.add(text);
                content.add(p, gbc);
                content.revalidate();
            }
        });
        JScrollPane scrollPane = new JScrollPane(content);
        f.pack();
        f.setLocationRelativeTo(null);
        f.add(scrollPane);
        f.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        new MyKskb();
    }
}

[结束]

[题]

我正在编写一个聊天程序,其布局如下所示:

带有消息的面板具有gridbaglayout,并包装在JScrollPane中。
问题是,如果消息太长,则消息面板会拉伸并变得太大:

所以我要实现的是限制包裹在jscrollpane中的面板的大小-我希望带有消息文本的灰色面板增加其高度,如果文本变长而不是变宽。即自动换行,而不增加面板宽度。

有没有办法用网格袋布局实现这一目标,我是否缺少某些东西?还是应该使用其他布局管理器?

编辑:完整层次结构:
JScrollPane
    JPanel (gbl)
        JPanel (custom painting)
            JComponent (JLabel but it can vary)
        JPanel (custom painting)
            JComponent (JLabel but it can vary)
        JPanel (custom painting)
            JComponent (JLabel but it can vary)
        ....

编辑:我试图实现Scrollable这样的:
@Override
    public Dimension getPreferredScrollableViewportSize(){
        return new Dimension(100, getHeight());
    }

    @Override
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction){
        return 5;
    }

    @Override
    public boolean getScrollableTracksViewportHeight(){
        return false;
    }

    @Override
    public boolean getScrollableTracksViewportWidth(){
        return true;
    }

    @Override
    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction){
        return 1;
    }

但是如果文本太长会发生同样的事情...我不知道getPreferredScrollableViewportSize应该返回什么,但是getSize()也不起作用...

编辑:这是一个脚本,它显示了我的GUI的基本结构:(按Enter添加新组件)
package de.sky.cjat;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;

public class Kskb {

    private int row;

    public Kskb(){
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setPreferredSize(new Dimension(800, 600));
        final JPanel content = new JPanel(new GridBagLayout());
        final JPanel empty = new JPanel();
        empty.setPreferredSize(new Dimension(0, 0));
        GridBagConstraints gbc = new GridBagConstraints();
        content.add(empty, gbc);
        content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "§");
        content.getActionMap().put("§", new AbstractAction(){
            @Override
            public void actionPerformed(ActionEvent e){
                JPanel p = new JPanel();
                p.setBackground(Color.GRAY);
                JLabel text = new JLabel("ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
                p.add(text);

                GridBagConstraints gbc = new GridBagConstraints();
                gbc.insets = new Insets(10, 10, 10, 10);
                gbc.weightx = 1.0;
                gbc.gridy = row++;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                gbc.anchor = GridBagConstraints.NORTHWEST;

                content.add(p, gbc);

                content.remove(empty);
                gbc.gridy = row;
                gbc.weighty = 1.0;
                content.add(empty, gbc);

                content.revalidate();
            }
        });
        JScrollPane scrollPane = new JScrollPane(content);
        f.pack();
        f.setLocationRelativeTo(null);
        f.add(scrollPane);
        f.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        new Kskb();
    }
}

最佳答案

遵循@durandal的建议,问题出在JLabel。 JLabel不换行。因此,您需要使用其他组件。这是使用JTextArea修改的代码:

import java.awt.*;
import java.awt.event.ActionEvent;

import javax.swing.*;
import javax.swing.border.*;

public class Kskb {

    private int row;

    public Kskb()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setPreferredSize(new Dimension(800, 600));
//        final JPanel content = new JPanel(new GridBagLayout());
        final ScrollablePanel content = new ScrollablePanel(new GridBagLayout());
        content.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
        final GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(10, 10, 10, 10);
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        content.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "");
        content.getActionMap().put("", new AbstractAction(){
            @Override
            public void actionPerformed(ActionEvent e)
            {
                JPanel p = new JPanel( new BorderLayout() );
                p.setBorder( new EmptyBorder(10, 10, 10, 10) );
                p.setBackground(Color.GRAY);
                JTextArea text = new JTextArea();
                text.append("ABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCABC ABCABCABCABCABCABCABCABCABCABCABCABCABCA BCABCABCABCABCABCABCAB CABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABC");
                text.setLineWrap( true );
                p.add(text);

                gbc.gridy = row++;
                content.add(p, gbc);
                content.revalidate();
            }
        });

        JScrollPane scrollPane = new JScrollPane(content);
        f.pack();
        f.setLocationRelativeTo(null);
        f.add(scrollPane);
        f.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        new Kskb();
    }
}

关键是Scrollable实现,它强制调整面板宽度以及调整框架。此代码使用Scrollable Panel,它只是Scrollable接口的可重用实现,您可以使用方法进行配置,而无需创建新类并覆盖方法。

10-01 00:28