import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class LineNumber extends JComponent {
static final long serialVersionUID = 3679449495322768618L;
private final static Color DEFAULT_BACKGROUND = new Color(140,140,140);//230, 163, 4
private final static Color DEFAULT_FOREGROUND = Color.blue;
private final static Font DEFAULT_FONT = new Font("monospaced", Font.PLAIN,12);
// LineNumber height (abends when I use MAX_VALUE)
private final static int HEIGHT = Integer.MAX_VALUE - 1000000;
// 设置左右页边空白
private final static int MARGIN = 5;
// Line height of this LineNumber component
private int lineHeight;
// Line height of this LineNumber component
private int fontLineHeight;
//当前行宽度
private int currentRowWidth;
// Metrics of this LineNumber component
private FontMetrics fontMetrics;
/**
* Convenience constructor for Text Components
*/
public LineNumber(JComponent component) {
if (component == null) {
setBackground(DEFAULT_BACKGROUND);
setForeground(DEFAULT_FOREGROUND);
setFont(DEFAULT_FONT);
} else {
setBackground(DEFAULT_BACKGROUND);
setForeground(component.getForeground());
setFont(component.getFont());
}
setPreferredSize(9999);
}
public void setPreferredSize(int row) {
int width = fontMetrics.stringWidth(String.valueOf(row));
if (currentRowWidth < width) {
currentRowWidth = width;
setPreferredSize(new Dimension(2 * MARGIN + width, HEIGHT));
}
}
public void setFont(Font font) {
super.setFont(font);
fontMetrics = getFontMetrics(getFont());
fontLineHeight = fontMetrics.getHeight();
}
/**
* The line height defaults to the line height of the font for this
* component. The line height can be overridden by setting it to a positive
* non-zero value.
*/
public int getLineHeight() {
if (lineHeight == 0)
return fontLineHeight;
else
return lineHeight;
}
public void setLineHeight(int lineHeight) {
if (lineHeight > 0)
this.lineHeight = lineHeight;
}
//起始偏移量
public int getStartOffset() {
return 4;
}
public void paintComponent(Graphics g) {
int lineHeight = getLineHeight();
int startOffset = getStartOffset();
Rectangle drawHere = g.getClipBounds();
// System.out.println( drawHere );
// Paint the background
g.setColor(getBackground());
g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);
// Determine the number of lines to draw in the foreground.
g.setColor(getForeground());
int startLineNumber = (drawHere.y / lineHeight) + 1;
int endLineNumber = startLineNumber + (drawHere.height / lineHeight);
int start = (drawHere.y / lineHeight) * lineHeight + lineHeight
- startOffset;
// System.out.println( startLineNumber + " : " + endLineNumber + " : " +
// start );
for (int i = startLineNumber; i <= endLineNumber; i++) {
String lineNumber = String.valueOf(i);
int width = fontMetrics.stringWidth(lineNumber);
g.drawString(lineNumber, MARGIN + currentRowWidth - width, start);
start += lineHeight;
}
setPreferredSize(endLineNumber);
}
public static void main(String[] args) {
JFrame frame = new JFrame("LineNumberDemo");
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭操作
JPanel panel = new JPanel();
frame.setContentPane(panel);
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
panel.setLayout(new BorderLayout());
JTextArea textPane = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textPane);
panel.add(scrollPane);
scrollPane.setPreferredSize(new Dimension(300, 250));
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
LineNumber lineNumber = new LineNumber(textPane);//look at here
lineNumber.setPreferredSize(99999);
scrollPane.setRowHeaderView(lineNumber);
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
frame.pack();
frame.setVisible(true);
}
}