JavaSwing中JTextPane中如何绘制行号

Posted David Wu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSwing中JTextPane中如何绘制行号相关的知识,希望对你有一定的参考价值。

Oracle在JTextPane类中并没有直接提供显示行号的方法,所以这个功能应该由程序员自己来完成,笔者发现网上很多的显示行号的代码都存在一个问题,就是不准确,特别是在行数变多了以后。

笔者先贴出代码:

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;

import javax.swing.ImageIcon;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.Position;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

public class EditPanel extends JTextPane {
    /**
     * 是否实现行号,默认不显示
     */
    private boolean showLineNumber = false;
    private int fontSize = 16;//默认为16号字体

    public EditPanel() {
        super();
    }
    public void setShowLineNumber(boolean isShow) {
        this.showLineNumber = isShow;
    }
    public boolean getShowLineNumber() {
        return this.showLineNumber;
    }
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        StyleConstants.setFontSize(getInputAttributes(), getFontSize());
        if (getShowLineNumber()) {
            drawLineNumber(g);
        }
    }
    protected void drawLineNumber(Graphics g) {
        setMargin(new Insets(0, 35, 0, 0));
        // 绘制行号的背景色
        g.setColor(new Color(180, 180, 180));
        g.fillRect(0, 0, 30, getHeight());
        // 获得有多少行
        StyledDocument docu = getStyledDocument();
        Element element = docu.getDefaultRootElement();
        int rows = element.getElementCount();
        // 绘制行号的颜色
        //System.out.println("y:" + getY());
        g.setColor(new Color(90, 90, 90));
        g.setFont(new Font(getFont().getName(), getFont().getStyle(), 16));
        for (int row = 0; row < rows; row++) {
            g.drawString((row + 1)+"",2, getPositionY(row + 1));
        }
    }
    public void setFontSize(int fontSize) {
        if(fontSize!=12 &&
           fontSize!=14 &&
           fontSize!=16 &&
           fontSize!=18 &&
           fontSize!=20 &&
           fontSize!=22 &&
           fontSize!=24 ){
            throw new RuntimeException("该行号不能识别");
        }
        this.fontSize = fontSize;
    }
    public int getFontSize() {
        return fontSize;
    }
    /**
     * 获得行号中y坐标的位置<br/>
     * 在计算的过程中,有一个比率值,该比率值是根据getY()的返回值之差决定的。
     * @param row 第几行
     * @return 该行的y坐标位置
     */
    private int getPositionY(int row) {
        int y = 0;
        switch (getFontSize()) {
        case 12:
            y = (row * 18) - 4;
            break;
        case 14:
            y = (row * 20) - 5;
            break;
        case 16:
            y = (row * 23) - 6;
            break;
        case 18:
            y = (row * 26) - 8;
            break;
        case 20:
            y = (row * 29) - 10;
            break;
        case 22:
            y = (row * 31) - 11;
            break;
        case 24:
            y = (row * 34) - 12;
            break;
        }
        return y;
    }
}
EditPanel.java

测试为:

    public static void main(String[] args) {
        JFrame jf=new JFrame("行号测试");
        EditPanel panel=new EditPanel();
        panel.setShowLineNumber(true);//显示行号
        
        jf.add(new JScrollPane(panel));
        jf.setPreferredSize(new Dimension(600,400));
        jf.pack();
        jf.setVisible(true);
    }

效果图:

一般在绘制行号的时候,都会牵扯到一个问题,就是如何定位Y的位置。笔者对这个问题的解决思路已经体现在上面的代码中了,下面再详细说一下。

首先贴出的EditPanel类中getPostionY()方法的部分代码:

        switch (getFontSize()) {
        case 12:
            y = (row * 18) - 4;
            break;

这里需要注意,这个18是由getY()获取得来的,在paint(Griphics g)中,打印getY()的值,然后得出变化的差值。经过笔者的测试发现,若字体设置为12号,那么getY()的变化差值就是18,那么每次行号Y的位置就是就是(第几行*18)的值,就可以让行号在每一行的前面了。然后再减4,是为了把行号往上提一点,显得好看。

其他的值以此类推。

 

以上是关于JavaSwing中JTextPane中如何绘制行号的主要内容,如果未能解决你的问题,请参考以下文章

如何将 HTML 字符串读入 JEditorPane/JTextPane?

如何在 JTextPane 中的一行上设置自定义背景颜色

Java Swing 文本字段中的 ANSI 颜色

在JTextPane java swing中填充直线矩形后无法与视图同步

突出显示 JTextPane 中的当前行

如何知道光标在哪个 JTextPane 中?