GridBagLayout 中的 JTextPane 行为不符合预期

JTextPane within a GridBagLayout do not behave the desired way

我在我的程序中遇到了以下问题。我在 JScrollPanel 中有一个带有 GridBagLayout 的 JPanel。它应该具有以下行为:

  1. 只能垂直滚动。
  2. JPanel 中的行是动态添加的。这些行有两列。两列都应平分 space。
  3. 这个table的每个字段(column/row)都是一个JTextPane,因为文本可以编辑,可以显示HTML。如果文本太长,它会被包裹起来,效果是字段的高度会增加。
  4. 调整 window 大小时,列也会调整。

问题是,当文本很长时:

如何才能获得所需的行为并避免这些问题?我已经用尽了所有我能想到的可能性。

这是使用 JTextPanes(但不使用 HTML)的所需行为的图片:

这是使用 JTextPanes 的错误行为:

这里是 SSCCE 的代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;

public class EditorTest extends JFrame {
    private JPanel jPanel1;
    private JPanel jPanel2;
    private JScrollPane jScrollPane1;
    private JTextPane jTextPane1;
    private JTextPane jTextPane2;

    public EditorTest() {
        initComponents();
    }

    private void initComponents() {
        GridBagConstraints gridBagConstraints;

        jScrollPane1 = new JScrollPane();
        jPanel2 = new JPanel();
        jPanel1 = new JPanel();
        jTextPane2 = new JTextPane();
        jTextPane1 = new JTextPane();

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(500, 500));
        getContentPane().setLayout(new GridBagLayout());

        jScrollPane1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        jPanel2.setBorder(BorderFactory.createEmptyBorder());
        jPanel2.setLayout(new BorderLayout());

        jPanel1.setLayout(new GridBagLayout());

        jTextPane2.setContentType("text/html"); 

        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.insets = new Insets(0, 0, 3, 3);
        jPanel1.add(jTextPane2, gridBagConstraints);

        jTextPane1.setContentType("text/html");
        jTextPane1.setText("This is a very long text that also sometimes is "
                + "<span style=\"color:blue\">blue</span> and so on and so on.");
        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.insets = new Insets(0, 0, 3, 3);
        jPanel1.add(jTextPane1, gridBagConstraints);

        jPanel2.add(jPanel1, BorderLayout.NORTH);


        jScrollPane1.setViewportView(jPanel2);

        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(jScrollPane1, gridBagConstraints);

        pack();
    }                     

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

非常感谢您的帮助!

更新1

为了使所需的行为更加清晰,我创建了另一个带有 JTextArea 的屏幕截图,就像头顶上的第一张图片一样。 TextPanes 应该位于顶部,并且只需要达到所需的高度(即文本)。为了说明此行为,还更改了文本字段的背景。

我想我已经编写了您想要的代码。

我必须为滚动窗格内的 JPanel 设置首选大小。宽度可以是任何你想要的。必须根据 JTextPanes 的大小调整高度。

这是 GUI 的图像。

这是代码。

package com.ggl.testing;

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;

public class EditorTest extends JFrame {
    private static final long serialVersionUID = 8019172274009058078L;

    private JPanel jPanel1;
    private JScrollPane jScrollPane1;
    private JTextPane jTextPane1;
    private JTextPane jTextPane2;

    public EditorTest() {
        initComponents();
    }

    private void initComponents() {
        GridBagConstraints gridBagConstraints;

        jScrollPane1 = new JScrollPane();
        jPanel1 = new JPanel();
        jTextPane2 = new JTextPane();
        jTextPane1 = new JTextPane();

        setTitle("Editor Test");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new GridBagLayout());

        jScrollPane1
                .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane1
                .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        jPanel1.setLayout(new GridLayout(0, 2));
        jPanel1.setPreferredSize(new Dimension(400, 400));

        jTextPane2.setContentType("text/html");
        jTextPane2
                .setText("<html>This is a very long text that also sometimes is "
                        + "<span style=\"color:green\">green</span> and so on and so on.");

        jTextPane1.setContentType("text/html");
        jTextPane1
                .setText("<html>This is a very long text that also sometimes is "
                        + "<span style=\"color:blue\">blue</span> and so on and so on.");

        jPanel1.add(jTextPane1);
        jPanel1.add(jTextPane2);

        jScrollPane1.setViewportView(jPanel1);

        gridBagConstraints = new GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(jScrollPane1, gridBagConstraints);

        pack();
    }

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

我认为你误解了我的意思所以这里 class 更清楚地向你展示 :

private class MyJTextPane extends JTextPane {
    public Dimension getPreferredSize() {
        return new Dimension(245,super.getPreferredSize().height);
    }
    public Dimension getMaximumSize() {
        return getPreferredSize();
    }
}

您可以在 SSCCE 中使用此 class 来查看它的行为方式。

这只是为了让您了解如何使用 getMaximumSize 和 getPreferredSize 来实现您的目标。您必须了解的是,对于给定的宽度,默认的 getPreferredSize 方法 returns 显示 JTextPane 内容所需的高度。

在您的情况下,您只需将 245 替换为您期望的最终宽度。如果宽度取决于其他元素,您也可以使用函数。

如果您需要更多详细信息,请告诉我。