如何获得具有多行功能的 JLabel? HTML真的是唯一的方法吗?
How do I get a JLabel with multiline capability? Is HTML really the only way?
我认为答案是 "you can't",但是关于 Swing 我还有很多不了解的地方。所以:
我需要显示只读的多行文本,一个字符一个字符,没有神奇的解释,在一个刚好能容纳它的矩形中。能够 select 一个区域(并从中复制)是一个优势。
到目前为止失败的方法:
JLabel("a\nb");
根本行不通,我无法想象为什么,因为这应该是唯一正确的答案。 JLabel 记录为显示交给它的文本。但显然不是换行符。
JLabel 有另一个可怕的问题:如果文本恰好以 <html>
开头,它又不会显示它收到的文本 - 它会将其重新解释为 HTML。文档不仅没有提到这一点,而且现在我遇到了一个问题,如果允许用户输入显示在 JLabel 中的文本(他们是),他们可以坚持格式化标签并导致各种欺骗(和他们会的)。
我找不到关闭此功能的方法;所以为了准确显示给定的文本,我必须预先处理文本以进行完整的 HTML 引用,并将 \n 更改为 <br>
,然后将其全部包装在 <html>...</html>
.我在核心 Java 中找不到引用的任何内容 - 显然你必须自己编写或依赖其他库,如 apache? Recommended method for escaping HTML in Java 给出了很多不依赖第三方库的理由。现在我的 java 代码将包含一个 HTML 布局引擎,以便我可以可靠地显示文本?我非常想避免这种未记录且脆弱的黑客行为。
JTextArea 可以处理多行文本,可以设置为只读。但我看不出如何告诉它缩小到只容纳文本所需的大小。 (JLabel 至少做对了。[编辑:或不 - 我恢复到 JLabel,现在标签在他们的行中居中或扩展到全尺寸 - 我显然在某处缺少设置])我认为必须有一种告诉它停止扩展以填充行的方法,但我该怎么做? setSize(1,1)
不这样做。我觉得正确的答案就在这条路上,但我需要一个指针来让它自动调整到最小尺寸。
或者有更好的组件吗?有没有办法将文本字符串呈现为最小尺寸的图像?我可以在 JLabel 中显示它...
我还试图避免扫描所有文本并组成一个左对齐 JLabel 的垂直框,每行一个 - 可能是可能的,但当有(也许?)一个更简单的解决方案时,它肯定比我想要的更复杂.
请注意,我无法对任何组件的大小进行硬编码。组件描述由服务器生成并传送到应用程序,应用程序根据描述动态生成小部件,并将它们添加到 Box 容器中。服务器无法以像素为单位进行计算;我需要依靠 Swing 来简单地根据 Boxes 中事物的顺序进行布局。在大多数情况下,这意味着小部件必须占据它们的最小可能大小。
我该怎么办?
按照指示我尝试了这个。只出现了一个窗格,而且没有边框,所以我看不出它会占用多少 space。
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
public class MainTextPane {
public static void main(final String[] args) {
Border loweredbevel = BorderFactory.createLoweredBevelBorder();
final JTextPane pane = new JTextPane();
pane.setText("Hello, this is a\ntwo lined string!");
final JTextPane pane2 = new JTextPane();
pane2.setText("Next!");
pane.setBorder(loweredbevel); //no effect
pane2.setBorder(loweredbevel); //no effect
final JFrame frame = new JFrame("TextPane with new lines.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pane);
frame.getContentPane().add(pane2); //clobbered previous pane
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
随时使用 JTextPane
which is a JEditorPane
. If you want the preferred size, just call getPreferredSize()
(设置文本后)。您可以将其设置为可编辑或不可编辑,并轻松地从中复制粘贴,它会处理新行。简单的使用就不需要复杂:
import javax.swing.JFrame;
import javax.swing.JTextPane;
public class MainTextPane {
public static void main(final String[] args) {
final JTextPane pane = new JTextPane();
pane.setText("Hello, this is a\nnew lined string! Hope JTextPane is what we are looking for here.");
final JFrame frame = new JFrame("TextPane with new lines.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
如果你要用任意文本加载它,我建议在 JScrollPane
中使用它,并根据你的需要设置 JScrollPane
的首选大小。
也测试了JEditorPane
,不会像JTextPane
那么简单。
如果您有更多要求,请在评论中告诉我们或更新您的问题。
编辑 1
关于您提供的代码,您看到第一个窗格 clobbers 第二个窗格,因为您将它们都添加到了内容窗格,而没有设置 LayoutManager
. Try setting the LayoutManager
to FlowLayout
例如(这会将两个窗格并排放置)。
按照斜角边框,我看得很清楚,但确实有点薄,所以你没看到的原因可能是这个。我 运行 你提供的代码也是,它是可见的,但不容易。无论如何,试试这个代码:
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
public class MainTextPane {
public static void main(final String[] args) {
Border loweredbevel = BorderFactory.createLoweredBevelBorder();
final JTextPane pane = new JTextPane();
pane.setText("Hello, this is a\ntwo lined string!");
final JTextPane pane2 = new JTextPane();
pane2.setText("Next!");
pane.setBorder(loweredbevel);
pane2.setBorder(loweredbevel);
final JFrame frame = new JFrame("TextPane with new lines.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout()); //Added this line of code...
frame.getContentPane().add(pane);
frame.getContentPane().add(pane2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
我认为答案是 "you can't",但是关于 Swing 我还有很多不了解的地方。所以:
我需要显示只读的多行文本,一个字符一个字符,没有神奇的解释,在一个刚好能容纳它的矩形中。能够 select 一个区域(并从中复制)是一个优势。
到目前为止失败的方法:
JLabel("a\nb");
根本行不通,我无法想象为什么,因为这应该是唯一正确的答案。 JLabel 记录为显示交给它的文本。但显然不是换行符。
JLabel 有另一个可怕的问题:如果文本恰好以 <html>
开头,它又不会显示它收到的文本 - 它会将其重新解释为 HTML。文档不仅没有提到这一点,而且现在我遇到了一个问题,如果允许用户输入显示在 JLabel 中的文本(他们是),他们可以坚持格式化标签并导致各种欺骗(和他们会的)。
我找不到关闭此功能的方法;所以为了准确显示给定的文本,我必须预先处理文本以进行完整的 HTML 引用,并将 \n 更改为 <br>
,然后将其全部包装在 <html>...</html>
.我在核心 Java 中找不到引用的任何内容 - 显然你必须自己编写或依赖其他库,如 apache? Recommended method for escaping HTML in Java 给出了很多不依赖第三方库的理由。现在我的 java 代码将包含一个 HTML 布局引擎,以便我可以可靠地显示文本?我非常想避免这种未记录且脆弱的黑客行为。
JTextArea 可以处理多行文本,可以设置为只读。但我看不出如何告诉它缩小到只容纳文本所需的大小。 (JLabel 至少做对了。[编辑:或不 - 我恢复到 JLabel,现在标签在他们的行中居中或扩展到全尺寸 - 我显然在某处缺少设置])我认为必须有一种告诉它停止扩展以填充行的方法,但我该怎么做? setSize(1,1)
不这样做。我觉得正确的答案就在这条路上,但我需要一个指针来让它自动调整到最小尺寸。
或者有更好的组件吗?有没有办法将文本字符串呈现为最小尺寸的图像?我可以在 JLabel 中显示它...
我还试图避免扫描所有文本并组成一个左对齐 JLabel 的垂直框,每行一个 - 可能是可能的,但当有(也许?)一个更简单的解决方案时,它肯定比我想要的更复杂.
请注意,我无法对任何组件的大小进行硬编码。组件描述由服务器生成并传送到应用程序,应用程序根据描述动态生成小部件,并将它们添加到 Box 容器中。服务器无法以像素为单位进行计算;我需要依靠 Swing 来简单地根据 Boxes 中事物的顺序进行布局。在大多数情况下,这意味着小部件必须占据它们的最小可能大小。
我该怎么办?
按照指示我尝试了这个。只出现了一个窗格,而且没有边框,所以我看不出它会占用多少 space。
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
public class MainTextPane {
public static void main(final String[] args) {
Border loweredbevel = BorderFactory.createLoweredBevelBorder();
final JTextPane pane = new JTextPane();
pane.setText("Hello, this is a\ntwo lined string!");
final JTextPane pane2 = new JTextPane();
pane2.setText("Next!");
pane.setBorder(loweredbevel); //no effect
pane2.setBorder(loweredbevel); //no effect
final JFrame frame = new JFrame("TextPane with new lines.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pane);
frame.getContentPane().add(pane2); //clobbered previous pane
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
随时使用 JTextPane
which is a JEditorPane
. If you want the preferred size, just call getPreferredSize()
(设置文本后)。您可以将其设置为可编辑或不可编辑,并轻松地从中复制粘贴,它会处理新行。简单的使用就不需要复杂:
import javax.swing.JFrame;
import javax.swing.JTextPane;
public class MainTextPane {
public static void main(final String[] args) {
final JTextPane pane = new JTextPane();
pane.setText("Hello, this is a\nnew lined string! Hope JTextPane is what we are looking for here.");
final JFrame frame = new JFrame("TextPane with new lines.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
如果你要用任意文本加载它,我建议在 JScrollPane
中使用它,并根据你的需要设置 JScrollPane
的首选大小。
也测试了JEditorPane
,不会像JTextPane
那么简单。
如果您有更多要求,请在评论中告诉我们或更新您的问题。
编辑 1
关于您提供的代码,您看到第一个窗格 clobbers 第二个窗格,因为您将它们都添加到了内容窗格,而没有设置 LayoutManager
. Try setting the LayoutManager
to FlowLayout
例如(这会将两个窗格并排放置)。
按照斜角边框,我看得很清楚,但确实有点薄,所以你没看到的原因可能是这个。我 运行 你提供的代码也是,它是可见的,但不容易。无论如何,试试这个代码:
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
public class MainTextPane {
public static void main(final String[] args) {
Border loweredbevel = BorderFactory.createLoweredBevelBorder();
final JTextPane pane = new JTextPane();
pane.setText("Hello, this is a\ntwo lined string!");
final JTextPane pane2 = new JTextPane();
pane2.setText("Next!");
pane.setBorder(loweredbevel);
pane2.setBorder(loweredbevel);
final JFrame frame = new JFrame("TextPane with new lines.");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout()); //Added this line of code...
frame.getContentPane().add(pane);
frame.getContentPane().add(pane2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}