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分层显示
创建一个透明的面板专门绘制线条,将其放在文本框面板的上层,通过分层面板控制显示顺序。
- 自定义绘制线条的透明面板:
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); } } }
- 使用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
相关产品推荐
相关产品推荐

