如何让带有 word-wrap 的 JTextArea 与 FormLayout 一起缩小?

How do I get JTextArea with word-wrap to shrink with FormLayout?

我需要一个 non-editable word-wrappable 文本 label/field/area 没有滚动条,它会随着 parent 没有滚动条调整大小。它将用于显示各种大小的文本,但 "always" 足以 space 显示全文。在极少数情况下,用户将 windows 调整得太小以至于无法容纳,我希望它截断 lines/vertically.

我已经进行了大量搜索并阅读了我可以在此处找到的任何相关问题,但没有找到问题的根源。我选择 JTextArea 是因为它具有 word-wrapping 的能力。我也尝试过 JLabel 的自定义扩展,但问题仍然存在,所以我认为我也可以坚持使用 JTextArea。 HTML 方法是我真正想避免的,原因有很多。这不是我第一次遇到这个问题,之前我已经通过妥协布局(以不同的方式设计表单)解决了这个问题。这肯定不是我最后一次面对这个问题,所以我想我需要找到一种方法而不是继续妥协。

问题在于,虽然这最初按预期工作并且当 window 的大小被调整为水平更大时,水平收缩 window 不会更新 word-wrapping,因此JTextArea 被水平截断。

我的测试表明这仅适用于某些布局管理器,但我不确定 "what level" 问题究竟出在哪里。我还在某处读到该问题仅存在于 Windows,但我没有 verified/tested。我正在使用 Windows 进行开发,所以我所知道的是问题就在这里,并且 Java 7 和 Java 8.

都存在

测试不同的布局管理器表明:

现有应用程序广泛使用 FormLayout,如果不进行大量重写,我无法更改它。将 JTextAreaJPanel 与其中一种工作布局包装在一起,例如 BorderLayout 只要 "broken" 布局之一在层次结构中更上层使用就无济于事.似乎有一些信号丢失并且没有到达 children,所以我被卡住了,因为我无法现实地摆脱 FormLayout 一直到层次结构的顶部.

这里有几个非常相似的现有问题,但很多是关于 JTextAreaJScrollPane 或其他一些细微变化的结合,none 帮助我找到了一个可行的方法解决方案。通过尽可能地缩小问题范围并提供一个有效的 SCCEE,我希望不会因为重复而被拒绝。

中总:

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.RowSpec;
import javax.swing.JTextArea;



public class MainFrame {

    private JFrame frame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                try {
                    MainFrame window = new MainFrame();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public MainFrame() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final JPanel panel = new JPanel(new FormLayout(
                    new ColumnSpec[] {ColumnSpec.decode("pref:grow"),},
                    new RowSpec[] {RowSpec.decode("pref:grow"),}
                ));
                frame.getContentPane().add(panel, BorderLayout.CENTER);
                final JTextArea textArea = new JTextArea();
                panel.add(textArea, "1, 1, fill, fill");
                textArea.setLineWrap(true);
                textArea.setText("Lorem ipsum dolor sit amet, ut eum assum debet tacimates, mei nisl electram moderatius ei, veri semper cotidieque eu pri. In quot noster vocent usu, ne augue voluptaria quo. Ex per malis vocibus. Consequat mediocritatem no vel.");
    }
}

您也许可以设置列大小...但您也可以将文本区域的 setPreferredSize 设置为 0,0:

import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

public class Test extends JFrame {
    final JPanel panel;
    final JTextArea textArea;
    final FormLayout fl;
    public Test() {
        this.setBounds(100, 100, 450, 300);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        fl = new FormLayout(
                new ColumnSpec[] {ColumnSpec.decode("pref:grow"), 
//                      ColumnSpec.decode("pref:grow")
                        },
                new RowSpec[] {RowSpec.decode("pref:grow"), 
//                      RowSpec.decode("pref:grow")
                        }
            );
        panel = new JPanel(fl);
        this.getContentPane().add(panel, BorderLayout.CENTER);
        textArea = new JTextArea();
        textArea.setPreferredSize(new Dimension());

        panel.add(new JPanel().add(textArea), "1, 1, fill, fill");
//        panel.add(new JPanel().add(new JLabel("test")), "1, 2, fill, fill");
//        panel.add(new JPanel().add(new JLabel("test")), "2, 1, fill, fill");
        textArea.setLineWrap(true);
//        textArea.setWrapStyleWord(true);
        textArea.setText("Lorem ipsum dolor sit amet, ut eum assum "
                + "debet tacimates, mei nisl electram moderatius ei, veri semper cotidieque eu pri. In quot noster vocent usu, "
                + "ne augue voluptaria quo. Ex per malis vocibus. Consequat mediocritatem no vel.");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Test().setVisible(true);
            }
        });
    }
}