JLabel是否有“自动换行”属性?

55
我正在JLabel中显示一些文本。基本上,我是动态生成这段文本,并使用一些HTML标签(如BRB)来格式化文本。最后,我将这个格式化的文本分配给我的JLabel。
现在我想让我的JLabel在屏幕末端时自动换行,就像记事本中的“自动换行”功能一样。
我该怎么做?

4
知情者告知一下,安德鲁的回答最好。 - Hovercraft Full Of Eels
@HovercraftFullOfEels <VBG> 我就知道屏幕截图会起作用的!</VBG> - Andrew Thompson
1
是的,我得开始多做一些这方面的事情,但有正确的答案还是很有帮助的。我想我应该学一点HTML和样式... - Hovercraft Full Of Eels
@AndrewThompson 它们很酷,但会让你的回答变慢! :) - MarianP
2
@HovercraftFullOfEels 对于第二句话加一,不仅仅是你,而是任何使用任何语言的服务器端开发人员。让我感到惊讶的是,(例如)servlet 开发人员对其应用程序所产生的 HTML 的理解是如此之少。至于第一句话...有些人可能认为我不断添加图像是视觉上的“噪音”。 - Andrew Thompson
@MarianP 没错,所以我用了一个小技巧。先发布源代码,然后在编辑中添加图片。当然,在这里没什么帮助,因为写这个(非常简短的)源代码比其他两个答案加选中标记的时间长。 ;) - Andrew Thompson
7个回答

99
可以使用HTML样式(CSS)为body设置宽度。这将决定要呈现的行数,从而确定标签的首选高度。 在CSS中设置宽度可以避免计算标签中的换行位置(或最佳大小)的需要。
import javax.swing.*;

public class FixedWidthLabel {

    public static void main(String[] srgs) {
        final String s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eu nulla urna. Donec sit amet risus nisl, a porta enim. Quisque luctus, ligula eu scelerisque gravida, tellus quam vestibulum urna, ut aliquet sapien purus sed erat. Pellentesque consequat vehicula magna, eu aliquam magna interdum porttitor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed sollicitudin sapien non leo tempus lobortis. Morbi semper auctor ipsum, a semper quam elementum a. Aliquam eget sem metus.";
        final String html = "<html><body style='width: %1spx'>%1s";

        Runnable r = () -> {
            JOptionPane.showMessageDialog(
                    null, String.format(html, 200, s));
            JOptionPane.showMessageDialog(
                    null, String.format(html, 300, s));
        };
        SwingUtilities.invokeLater(r);
    }
}

enter image description here enter image description here


1
是的,这个是赢家。 :) - Hovercraft Full Of Eels
11
如果你需要一个可变宽度的标签,可以使用"100%"代替"200px"(假设你的GUI使用适当的布局管理器)。+1 - camickr
3
如果这是用于浏览器的HTML,是的。但这只是用于Swing组件的HTML,我们可以采用许多快捷方式。其中一个优点是它允许我们(轻松地)动态添加新内容到HTML中。例如: label.setText(label.getText() + "<li>新列表项"); - Andrew Thompson
刚刚注意到带有<html>标签的JLabel在使用本地L&F的Vista和7上看起来不同:https://trello-attachments.s3.amazonaws.com/51b5f6a477d99db360005655/53995637865128f50782b410/1698x1314/315f89565f34cc9fa9d95f858e45e287/Screen_Shot_2014-06-12_at_11.26.14_AM.png - Ivan Nikitin
3
请记住,某些字符需要进行转义或转换为它们的 HTML 实体。 - Chris Dennett
@ChrisDennett 是的,你说得对,这是需要注意和留意的事情。 - Andrew Thompson

35

如果您将文本包装在<html>...</html>中,应该可以正常工作。

更新: 您还应该设置最大大小。


我已经将文本包装在HTML中,例如<html>一些文本 <br/> <b>一些文本<b> </html> 我需要使用特定的HTML标签来包装吗? - Jame
尝试在该JLabel上调用setMaximumSize。 - MarianP
1
"<html>一些文本 <br/>" 网页开发者们都要翻身了。请使用样式。 - Andrew Thompson
3
@Jame:FYI,Netbeans与你的问题无关 - 它只是一个IDE。Java是你问题的主题... - Andy
我刚刚想象了Flash在JLabel中运行,这让我差点笑翻了。 - MarianP
显示剩余4条评论

12
一种方法是使用JTextArea代替JLabel,并将setWrapStyleWordsetLineWrap设置为true,并进行其他设置使其外观和行为像JLabel(去掉边框,使其非不透明,使其不能编辑和获取焦点)。
否则,如果你绝对需要使用JLabel,则必须使用FontMetrics来测量文本的大小,检查空格,并在适当位置添加HTML硬断点。

2
"添加HTML硬换行符。" Web开发者们都要在坟墓里翻转了。使用样式。 - Andrew Thompson
6
我显然不是网页开发者。谢谢你提醒我,也向所有不眠之夜的离世的网页开发者致以歉意和敬意。 - Hovercraft Full Of Eels
这是当前的实现方式,一旦格式化字符串大于标签的尺寸,它就无法工作。 - Steve Cohen

9
我发现这个解决方案最简单,而且在调整大小时也能正常工作。除了用 <html> 标签包装文本之外,你还必须将标签放入一个保持优先高度并将宽度设置为最大的容器中。例如,你可以将标签放入 BorderLayout 的 NORTH 区域。
以下是一个简单但完整的工作程序,以说明这一点。您可以按任何方式调整框架的大小;标签将占据整个宽度,高度将相应地调整以包裹文本。请注意,我所做的一切都是使用 <html> 标签,并将标签放在 BorderLayout 的 NORTH 区域。
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import java.awt.Dimension;

public class LabelWrap {

    public static JPanel createPanel() {
        JLabel label = new JLabel();
        label.setText("<html>"
            + "<h3>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</h3>"
            + "<p>Duis a tincidunt urna. Phasellus tristique interdum mauris, "
            + "ut vestibulum purus suscipit eget. Aenean massa elit, accumsan "
            + "non faucibus vel, dictum placerat urna. In bibendum est sagittis "
            + "urna iaculis quis sagittis velit commodo. Cum sociis natoque "
            + "penatibus et magnis dis parturient montes, nascetur ridiculus "
            + "mus. Nam quis lacus mauris. Phasellus sem libero, convallis "
            + "mattis sagittis vel, auctor eget ipsum. Vivamus molestie semper "
            + "adipiscing. In ac neque quis elit suscipit pharetra. Nulla at "
            + "orci a tortor consequat consequat vitae sit amet elit. Praesent "
            + "commodo lacus a magna mattis vehicula. Curabitur a hendrerit "
            + "risus. Aliquam accumsan lorem quis orci lobortis malesuada.</p>"
            + "<p>Proin quis viverra ligula. Donec pulvinar, dui id facilisis "
            + "vulputate, purus justo laoreet augue, a feugiat sapien dolor ut "
            + "nisi. Sed semper augue ac felis ultrices a rutrum dui suscipit. "
            + "Praesent et mauris non tellus gravida mollis. In hac habitasse "
            + "platea dictumst. Vestibulum ante ipsum primis in faucibus orci "
            + "luctus et ultrices posuere cubilia Curae; Vestibulum mattis, "
            + "tortor sed scelerisque laoreet, tellus neque consectetur lacus, "
            + "eget ultrices arcu mi sit amet arcu. Nam gravida, nulla interdum "
            + "interdum gravida, elit velit malesuada arcu, nec aliquam lectus "
            + "velit ut turpis. Praesent pretium magna in nibh hendrerit et "
            + "elementum tellus viverra. Praesent eu ante diam. Proin risus "
            + "eros, dapibus at eleifend sit amet, blandit eget purus. "
            + "Pellentesque eu mollis orci. Sed venenatis diam a nisl tempor "
            + "congue.</p>"
            + "</html>");

        JPanel panel = new JPanel(new BorderLayout());
        panel.add(label, BorderLayout.NORTH);
        panel.setPreferredSize(new Dimension(640, 480));
        return panel;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() { 
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setContentPane(createPanel());
                frame.pack();
                frame.setVisible(true);
            }

        });
    }

}

0
我喜欢上面提到的JTextArea方法,因为它在BorderLayout面板的SOUTH区域可以很好地调整大小(只要CENTER组件可以填补JTextArea行数变化时的空缺)。
然而,在Nimbus L&F中,设置JTextArea的背景颜色有一个问题。似乎Nimbus使用了魔术颜色(java.awt.Color的扩展类),在JTextArea中会变成透明色。所以,如果你想将JPanel的背景颜色复制到JTextArea中,你需要将Color转换为ARGB,然后再转回Color。以下代码适用于我JRE中的所有L&Fs(Nimbus、CDE Motif、Metal、Mac OS X):
    JTextArea ta = new JTextArea(text);
    ta.setEditable(false);
    ta.setLineWrap(true);
    ta.setWrapStyleWord(true);
    JLabel lb = new JLabel();
    Font f = lb.getFont();
    ta.setFont(f.deriveFont(f.getSize2D() * 0.9f));
    ta.setBorder(lb.getBorder());
    ta.setBackground(new Color(lb.getBackground().getRGB(), true));
    ta.setForeground(new Color(lb.getForeground().getRGB(), true));
    ta.setOpaque(lb.isOpaque());

我把字体稍微调小了一点。当然,如果你想保持JLabel的字体大小也可以。


1
请尽量保持话题相关。 - Jordi
我相信我保持了主题的连贯性。我指出了使用JTextArea时遇到的两个问题(重设大小时行数变化和在Nimbus中设置颜色),并提供了两种解决方法。 - Adam Gawne-Cain

0

混合使用纯文本和HTML将关闭HTML中的自动换行功能:

    jLabel_01.setText("<html>Lorem ipsum long paragraph</html>"); // work good
...
    jLabel_01.setText(""); // will switch off HTML words wrap!!!
...
    jLabel_01.setText("<html>Lorem ipsum long paragraph</html>"); // will not work properly

因此,您不能在一个JLabel中混合不同类型(HTML和纯文本)的文本


-2

我想为那些在互联网上搜索的人发布这篇文章,因为这是一个小错误,让我浪费了30分钟。请确保你已经将文本包装在HTML中。你可能认为你已经这样做了,但实际上并没有。检查一下,我忘记了,当我将它们包装在HTML中时,问题就解决了。

JLabel label = new JLabel("Lorem ipsum long paragraph"); 错误的。

JLabel label = new JLabel("<html>Lorem ipsum long paragraph</html>"); 正确的!


抱歉,Nabin,这已经很久以前的事情了,我真的记不起来任何相关的内容了。 - Adam K Dean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接