【Java】Swing中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; } }
测试为:
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,是为了把行号往上提一点,显得好看。
其他的值以此类推。