GridBagLayout 中的 JTextPane 行为不符合预期
JTextPane within a GridBagLayout do not behave the desired way
我在我的程序中遇到了以下问题。我在 JScrollPanel 中有一个带有 GridBagLayout 的 JPanel。它应该具有以下行为:
- 只能垂直滚动。
- JPanel 中的行是动态添加的。这些行有两列。两列都应平分 space。
- 这个table的每个字段(column/row)都是一个JTextPane,因为文本可以编辑,可以显示HTML。如果文本太长,它会被包裹起来,效果是字段的高度会增加。
- 调整 window 大小时,列也会调整。
问题是,当文本很长时:
- 在不使用 PreferredSize 的情况下使用 JTextPane 时,换行不起作用,并且列不会平均分配。设置首选大小后,JTextPane 会剪切第二行中的文本。 JEditorPane 也不起作用。
- 当使用带有激活换行的 JTextArea 时,效果很好!但是,我无法显示 HTML。此外,第四点没有实现。扩展 window 时,该字段也会调整大小。但是当再次缩小 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 替换为您期望的最终宽度。如果宽度取决于其他元素,您也可以使用函数。
如果您需要更多详细信息,请告诉我。
我在我的程序中遇到了以下问题。我在 JScrollPanel 中有一个带有 GridBagLayout 的 JPanel。它应该具有以下行为:
- 只能垂直滚动。
- JPanel 中的行是动态添加的。这些行有两列。两列都应平分 space。
- 这个table的每个字段(column/row)都是一个JTextPane,因为文本可以编辑,可以显示HTML。如果文本太长,它会被包裹起来,效果是字段的高度会增加。
- 调整 window 大小时,列也会调整。
问题是,当文本很长时:
- 在不使用 PreferredSize 的情况下使用 JTextPane 时,换行不起作用,并且列不会平均分配。设置首选大小后,JTextPane 会剪切第二行中的文本。 JEditorPane 也不起作用。
- 当使用带有激活换行的 JTextArea 时,效果很好!但是,我无法显示 HTML。此外,第四点没有实现。扩展 window 时,该字段也会调整大小。但是当再次缩小 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 替换为您期望的最终宽度。如果宽度取决于其他元素,您也可以使用函数。
如果您需要更多详细信息,请告诉我。