您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Java用省略号截断字符串的理想方法

Java用省略号截断字符串的理想方法

我喜欢让“瘦”字符算作半个字符的想法。简单而良好的近似。

然而,大多数省略的主要问题是(imho)他们在中间砍了字。这是一个考虑单词边界的解决方案(但不涉及像素数学和Swing-API)。

private final static String NON_THIN = "[^iIl1\\.,']";

private static int textWidth(String str) {
    return (int) (str.length() - str.replaceAll(NON_THIN, "").length() / 2);
}

public static String ellipsize(String text, int max) {

    if (textWidth(text) <= max)
        return text;

    // Start by chopping off at the word before max
    // This is an over-approximation due to thin-characters...
    int end = text.lastIndexOf(' ', max - 3);

    // Just one long word. Chop it off.
    if (end == -1)
        return text.substring(0, max-3) + "...";

    // Step forward as long as textWidth allows.
    int newEnd = end;
    do {
        end = newEnd;
        newEnd = text.indexOf(' ', end + 1);

        // No more spaces.
        if (newEnd == -1)
            newEnd = text.length();

    } while (textWidth(text.substring(0, newEnd) + "...") < max);

    return text.substring(0, end) + "...";
}

似乎您可以从Java图形上下文的中获得更准确的几何图形FontMetrics。

附录:解决此问题时,可能有助于区分模型和视图。模型是StringUTF-16代码点的有限序列,而视图是一系列字形,以某种字体在某些设备上呈现。

在Java的特定情况下,可以使用JavaSwingUtilities.layoutCompoundLabel()进行翻译。下面的示例拦截了布局调用BasicLabelUI以演示效果。在其他情况下也可以使用实用程序方法,但是FontMetrics必须根据经验确定适当的方法

替代文字

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.plaf.basic.BasicLabelUI;

/** @see http://stackoverflow.com/questions/3597550 */
public class LayoutTest extends JPanel {

    private static final String text =
        "A damsel with a dulcimer in a vision once I saw.";
    private final JLabel sizeLabel = new JLabel();
    private final JLabel textLabel = new JLabel(text);
    private final MyLabelUI myUI = new MyLabelUI();

    public Layouttest() {
        super(new GridLayout(0, 1));
        this.setBorder(BorderFactory.createCompoundBorder(
            new LineBorder(Color.blue), new EmptyBorder(5, 5, 5, 5)));
        textLabel.setUI(myUI);
        textLabel.setFont(new Font("Serif", Font.ITALIC, 24));
        this.add(sizeLabel);
        this.add(textLabel);
        this.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                sizeLabel.setText(
                    "Before: " + myUI.before + " after: " + myUI.after);
            }
        });
    }

    private static class MyLabelUI extends BasicLabelUI {

        int before, after;

        @Override
        protected String layoutCL(
            JLabel label, FontMetrics fontMetrics, String text, Icon icon,
            Rectangle viewR, Rectangle iconR, Rectangle textR) {
            before = text.length();
            String s = super.layoutCL(
                label, fontMetrics, text, icon, viewR, iconR, textR);
            after = s.length();
            System.out.println(s);
            return s;
        }
    }

    private void display() {
        JFrame f = new JFrame("LayoutTest");
        f.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokelater(new Runnable() {

            @Override
            public void run() {
                new Layouttest().display();
            }
        });
    }
}
java 2022/1/1 18:21:55 有544人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶