You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java数独程序:如何让绘制线条显示在JTextField上方?

解决Java数独GUI线条被JTextField覆盖的问题

核心原因

Swing组件的绘制顺序是:容器先调用自身paintComponent绘制内容,再依次绘制所有子组件。所以你在容器paintComponent里画的线条会被子组件(JTextField)覆盖。要让线条显示在文本框上方,需要调整绘制顺序。

方案一:重写容器的paint方法(推荐,代码更简洁)

直接在存放文本框的gridPanel中重写paint方法,先绘制子组件(文本框),再绘制数独线条,这样线条就会覆盖在文本框之上。

修改后的gridPanel代码:

// 创建gridPanel时重写paint方法
gridPanel = new JPanel(new GridLayout(9, 9)) {
    @Override
    public void paint(Graphics g) {
        // 先绘制所有子组件(文本框)
        super.paintChildren(g);
        // 再绘制数独线条,此时线条会在文本框上方
        Graphics2D g2d = (Graphics2D) g;
        int squareSize = yourSquareSizeVariable; // 替换成你的squareSize变量

        // 绘制3x3区块的粗分隔线
        g2d.setStroke(new BasicStroke(2));
        for (int i = 3; i < 9; i += 3) {
            int pos = i * squareSize;
            g2d.drawLine(pos, 0, pos, getHeight());
            g2d.drawLine(0, pos, getWidth(), pos);
        }

        // 绘制每个格子的细分隔线
        g2d.setStroke(new BasicStroke(1));
        for (int i = 1; i < 9; i++) {
            int pos = i * squareSize;
            g2d.drawLine(pos, 0, pos, getHeight());
            g2d.drawLine(0, pos, getWidth(), pos);
        }
    }
};

// 下面是原来的文本框添加代码,保持不变
gridPanel.setPreferredSize(new Dimension(squareSize * 9, squareSize * 9));
for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {
        JTextField textField = new JTextField(1);
        textField.setHorizontalAlignment(JTextField.CENTER);
        textField.setFont(new Font("Arial", Font.PLAIN, 24));
        // 可选:去掉文本框边框,避免和数独线条重复
        textField.setBorder(BorderFactory.createEmptyBorder());
        gridPanel.add(textField);
        textFields[i][j] = textField;
    }
}
this.add(gridPanel);

方案二:使用JLayeredPane分层显示

创建一个透明的面板专门绘制线条,将其放在文本框面板的上层,通过分层面板控制显示顺序。

  1. 自定义绘制线条的透明面板:
class SudokuOverlay extends JPanel {
    private int squareSize;

    public SudokuOverlay(int squareSize) {
        this.squareSize = squareSize;
        setOpaque(false); // 关键:设置透明,不遮挡下方的文本框
        setPreferredSize(new Dimension(squareSize * 9, squareSize * 9));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        // 绘制数独线条的代码和你原来的一致
        g2d.setStroke(new BasicStroke(2));
        for (int i = 3; i < 9; i += 3) {
            int pos = i * squareSize;
            g2d.drawLine(pos, 0, pos, squareSize * 9);
            g2d.drawLine(0, pos, squareSize * 9, pos);
        }
        g2d.setStroke(new BasicStroke(1));
        for (int i = 1; i < 9; i++) {
            int pos = i * squareSize;
            g2d.drawLine(pos, 0, pos, squareSize * 9);
            g2d.drawLine(0, pos, squareSize * 9, pos);
        }
    }
}
  1. 使用JLayeredPane组合两个面板:
// 原来的文本框面板代码保持不变
gridPanel = new JPanel(new GridLayout(9, 9));
gridPanel.setPreferredSize(new Dimension(squareSize * 9, squareSize * 9));
for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {
        JTextField textField = new JTextField(1);
        textField.setHorizontalAlignment(JTextField.CENTER);
        textField.setFont(new Font("Arial", Font.PLAIN, 24));
        textField.setBorder(BorderFactory.createEmptyBorder());
        gridPanel.add(textField);
        textFields[i][j] = textField;
    }
}

// 创建分层面板
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(squareSize * 9, squareSize * 9));

// 将文本框面板添加到底层
gridPanel.setBounds(0, 0, squareSize * 9, squareSize * 9);
layeredPane.add(gridPanel, JLayeredPane.DEFAULT_LAYER);

// 将线条覆盖面板添加到上层
SudokuOverlay overlay = new SudokuOverlay(squareSize);
overlay.setBounds(0, 0, squareSize * 9, squareSize * 9);
layeredPane.add(overlay, JLayeredPane.PALETTE_LAYER);

// 将分层面板添加到窗口
this.add(layeredPane);

两种方案都能实现线条在文本框上方的效果,方案一代码更精简,无需额外组件,优先推荐。

内容的提问来源于stack exchange,提问作者Freddy Redpath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 22:42:09