JTextPane 行数包括图标和组件

JTextPane Line Count Including Icons and Components

我最近一直在为即将开展的项目试验 JTextPanes 的用户,网上有各种帖子详细介绍了如何计算文本窗格中的行数,但是解决方案我发现将图标或组件插入文本窗格的文档时似乎都失败了。

我发现适用于纯文本的解决方案是这个(当然实现了解决方案):BadLocationException when using Utilities.getRowStart On hit of Enter key

但是,一旦我尝试为此插入组件 (JLabel) 或普通图标,Utilities 中的 getRowStart() 方法就会引发空指针异常。我发现这不寻常的是 Java Doc 指出“......这在相关文档中表示为内容的一个字符的属性。”,所以我假设它会把它当作任何其他字符但是好像不是这样。

我提供了一个代码示例来重现该问题,如果有人想尝试的话。我有一种感觉,这根本不可能,这将是一种耻辱。

import java.awt.Dimension;
import java.awt.Image;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;

public class Test{

    private JFrame frame;
    private JTextPane textPane;

    private Image img;
    private URL imgURL;

    public Test(){
        frame = new JFrame();
        frame.setSize(new Dimension(500,300));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        textPane = new JTextPane();

        try {
            imgURL = new URL("http://www.freeiconspng.com/uploads/floppy-save-icon--23.png");
            img = ImageIO.read(imgURL);
            JLabel label = new JLabel(new ImageIcon(img.getScaledInstance(10, 10, Image.SCALE_SMOOTH)));

            textPane.insertComponent(label);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        frame.getContentPane().add(textPane);
        frame.setVisible(true);

    }
    public JTextPane getTextPane(){
        return this.textPane;
    }
    public int getLineCount(){
        int totalCharacters = textPane.getDocument().getLength(); 
        int lineCount = (totalCharacters == 0) ? 1 : 0;

        try {
           int offset = totalCharacters; 
           while (offset > 0) {
              offset = Utilities.getRowStart(textPane, offset) - 1;
              lineCount++;
           }
        } catch (BadLocationException e) {
            e.printStackTrace();
        }

        return lineCount;
    }
    public static void main(String[] args){
        Test t = new Test();
        t.getLineCount();
    }
}

经过以下评论问题已解决:

It doesn't throw any exception for me once I wrap the content inside your main method inside a EventQueue.invokeLater() call. I.e.:

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        Test t = new Test();
        t.getLineCount();
    }
});