• JTextArea 显示行号


    系统:Win10
    JDK:1.8.0_333
    IDEA:2020.3.4

    1.需求描述

    最近在做一个 Swing 项目的时候,使用到了 JTextArea 组件,然后需要显示文本处于多少行,在左边需要显示它的行号,并且会随着行号的增加,显示行号的面板的宽度会自动扩展开

    2.代码实现

    import javax.swing.*;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.Document;
    import java.awt.*;
    
    /**
     * @ClassName MyTextArea
     * @Description 实现 JTextArea 显示行号
     * @Author Li
     * @Date 2022/8/28 13:55
     * @ModifyDate 2022/8/28 13:55
     * @Version 1.0
     */
    public class MyTextArea extends JPanel {
        private LinePanel linePanel;
    
        private JTextArea textArea;
    
        private JScrollPane scrollPane;
    
        public MyTextArea() {
            this.setLayout(new BorderLayout());
            linePanel = new LinePanel();
            linePanel.setPreferredSize(new Dimension(25, 10));
            this.textArea = new JTextArea() {
                public void paint(Graphics g) {
                    super.paint(g);
                    linePanel.repaint();
                }
            };
            this.scrollPane = new JScrollPane(this.textArea);
            this.add(linePanel, BorderLayout.WEST);
            this.add(scrollPane, BorderLayout.CENTER);
        }
    
        // 内部类:显示行号的面板
        private class LinePanel extends JPanel {
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                // starting pos in document
                int start = textArea.viewToModel(scrollPane.getViewport().getViewPosition());
                // end pos in doc
                int end = textArea.viewToModel(new Point(scrollPane.getViewport().getViewPosition().x + textArea.getWidth()
                        , scrollPane.getViewport().getViewPosition().y + textArea.getHeight()));
    
                // translate offsets to lines
                Document doc = textArea.getDocument();
                int startLine = doc.getDefaultRootElement().getElementIndex(start) + 1;
                int endLine = doc.getDefaultRootElement().getElementIndex(end) + 1;
    
                int fontHeight = g.getFontMetrics(textArea.getFont()).getHeight();
                int fontDesc = g.getFontMetrics(textArea.getFont()).getDescent();
                int starting_y = -1;
                
                try {
                    starting_y = textArea.modelToView(start).y -
                            scrollPane.getViewport().getViewPosition().y + fontHeight - fontDesc;
                } catch (BadLocationException ble) {
                    ble.printStackTrace();
                }
    
                for (int line = startLine, y = starting_y; line <= endLine; y += fontHeight, line++) {
                    g.drawString(Integer.toString(line), getNumX(line), y);
                }
            }
    
            // 获取当前行的行号 x 坐标
            private int getNumX(int line) {
                int width = linePanel.getWidth() - 5;
                FontMetrics metrics = linePanel.getFontMetrics(this.getFont());
                int fontHeight = metrics.getHeight();
                int fontWidth = metrics.stringWidth("0");
                int digit = 0;
                while (line > 0) {
                    line = line / 10;
                    digit++;
                }
                int x = width - digit * fontWidth;
                // 自适应调整宽度
                if (x < 5) {
                    linePanel.setPreferredSize(new Dimension(getWidth() + fontWidth, fontHeight));
                    linePanel.updateUI();
                }
                return x;
            }
        }
    
        // 主方法测试
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            frame.setTitle("JTextArea显示行号");
            frame.setLayout(new BorderLayout());
            MyTextArea textArea = new MyTextArea();
            frame.getContentPane().add(textArea, BorderLayout.CENTER);
            frame.setSize(new Dimension(400, 300));
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    3.效果演示

    在这里插入图片描述

  • 相关阅读:
    化工&python | CSTR连续搅拌反应器系统
    “攻城狮”如何写高逼格的代码
    Unity中实现溶解(Dissolve)特效及其原理解析
    Linux虚拟机安装:VMware安装配置&&CentOS安装
    Qt5开发从入门到精通——第六篇三节( 图像与图片——双缓冲机制)
    nginx七层负载均衡配置
    【算法题】2034. 股票价格波动
    SQL设计时增加说明列
    基于nodejs+vue云旅青城系统
    SMT生产中基板的机械清洁处理法有哪些
  • 原文地址:https://blog.csdn.net/qq_35132089/article/details/126775378