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

Java Swing窗口调整时JTextField重叠问题求助

问题描述

尝试基于二维数组创建类似数独的居中数字网格,使用Java Swing实现,但调整应用窗口大小时,调整前的JTextField会出现重叠,界面变得混乱。

代码示例

package graphics;
import java.awt.*;

import javax.swing.JPanel;
import javax.swing.JTextField;
public class Table  {
    int currentX;
    int currentY;
    final Color currrentColor = Color.yellow;
    final Color pasteColor = Color.red;
    int[][] array;
    int[][] selectedCase;
    int selectedSize;
    TableRepresentation tab;
    void setRepresentation(Color backgroundColor, int width, int height) 
    {
       tab = new TableRepresentation(backgroundColor,width,height);
    }
    JPanel getRepresentation() 
    {
        
        return tab;
    }
    public Table(int[][] array)
    {
        this.array = array;
        selectedCase = new int[2][array.length * array[0].length];
        currentX = 0;
        currentY = 0;
        selectedSize = 0;
        updateCase(currentX , currentY);
    }
    public void updateCase(int x , int y) {
        currentX = x;
        currentY = y;
        selectedCase[0][selectedSize] = x;
        selectedCase[1][selectedSize] = y;
        selectedSize++;
    }
    private class TableRepresentation extends JPanel {
        double width;
        double height;
        Dimension ceil;
        TableRepresentation(Color backgroundColor, int width, int height){
            setSize(width, height);
            setBackground(backgroundColor);
            this.width = (double) width / array[0].length - 3;
            this.height = (double) height / array.length - 3;
            ceil = new Dimension((int)this.width - 2,(int)this.height - 2);
            
        }
        
        void createGrid(Graphics2D g2d) {
            g2d.drawRect(0,0,getWidth(), getWidth());
            for (int i = 1; i <= array[0].length ; i++) 
            {
                if (i == 1) 
                {
                    g2d.drawLine((5+(int) width) * i,0,(5+(int) width) * i,getWidth());
                }
                g2d.drawLine((4+(int) width) * i,0,(4+(int) width) * i,getWidth());
            }
            for (int i = 1; i < array[0].length ; i++) 
            {
                if (i == 1) 
                {
                    g2d.drawLine(0,((int) height + 5) * i,getHeight(),((int) height + 5) * i);
                }
                g2d.drawLine(0,((int) height + 4) * i,getHeight(),((int) height + 4) * i);
            }
            
        }
        Point getCeilAtLocation(int x, int y) {
            return new Point(3 + ((int) width + 3) * x,(3 + ((int) height + 3) * y));
        }
        JTextField setAtributes() {
            JTextField text = new JTextField();
            text.setSize(ceil);
            text.setBorder(null);
            text.setEditable(false);
            text.setFocusable(false);
            text.setForeground(Color.white);
            text.setBackground(Color.BLACK);
            text.setFont(new Font("Arial", Font.PLAIN,(int) width - 10));
            text.setHorizontalAlignment(JTextField.CENTER);
            
            return text;
        }
        void createNumbers()
        {
            
            JTextField text = null;
     
            for (int i = 0; i < array.length; i++) 
            {
                for (int j = 0; j < array[0].length; j++) 
                {
                    text = setAtributes();
                    text.setText(Integer.toString(array[i][j]));
                    text.setLocation(getCeilAtLocation(j,i));
                    add(text, -1);
                    text.setVisible(true);
                }
                
            }
            
        }
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.white);
            Stroke basic = new BasicStroke(3);
            g2d.setStroke(basic);
            createGrid(g2d);
            createNumbers();
            
        }
    }
}

疑问

请问如何阻止JTextField出现重叠?


解决方案

核心问题原因

代码在每次paintComponent调用时都会执行createNumbers(),而这个方法会不断创建新的JTextField并添加到面板中,窗口调整时会触发多次重绘,导致旧的文本框没有被移除,新的又被添加,最终出现重叠。

修复步骤

  1. 提前创建并缓存JTextField:在TableRepresentation初始化时一次性创建所有文本框,而非每次重绘都新建。
  2. 重绘时只更新位置和大小:窗口调整时,仅修改已有文本框的位置、大小和字体,不创建新组件。
  3. 移除paintComponent中的createNumbers()调用:避免重复添加组件。

修改后的关键代码

1. 在TableRepresentation中添加成员变量存储文本框数组

private JTextField[][] textFields; // 缓存所有文本框

2. 在构造方法中初始化文本框

TableRepresentation(Color backgroundColor, int width, int height){
    setSize(width, height);
    setBackground(backgroundColor);
    // 初始化文本框数组
    textFields = new JTextField[array.length][array[0].length];
    updateDimensions(width, height); // 提取尺寸计算到单独方法
    // 一次性创建所有文本框
    for (int i = 0; i < array.length; i++) {
        for (int j = 0; j < array[0].length; j++) {
            textFields[i][j] = setAtributes();
            textFields[i][j].setText(Integer.toString(array[i][j]));
            add(textFields[i][j], -1);
        }
    }
}

3. 添加尺寸更新方法,用于窗口调整时刷新

private void updateDimensions(int width, int height) {
    this.width = (double) width / array[0].length - 3;
    this.height = (double) height / array.length - 3;
    ceil = new Dimension((int)this.width - 2,(int)this.height - 2);
    // 更新所有文本框的大小、位置和字体
    if (textFields != null) {
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[0].length; j++) {
                textFields[i][j].setSize(ceil);
                textFields[i][j].setLocation(getCeilAtLocation(j,i));
                textFields[i][j].setFont(new Font("Arial", Font.PLAIN,(int) width - 10));
            }
        }
    }
}

4. 重写setSize方法,窗口调整时触发尺寸更新

@Override
public void setSize(int width, int height) {
    super.setSize(width, height);
    updateDimensions(width, height); // 尺寸变化时更新文本框
}

5. 修改paintComponent方法,移除createNumbers()调用

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.white);
    Stroke basic = new BasicStroke(3);
    g2d.setStroke(basic);
    createGrid(g2d);
    // 不再调用createNumbers()
}

额外优化建议

  • 使用GridLayout等布局管理器替代手动计算位置和大小,Swing布局管理器会自动处理组件排列和尺寸调整,减少手动计算错误。
  • 如果不需要编辑功能,直接用JLabel替代JTextField,更轻量且避免不必要的交互特性。

内容的提问来源于stack exchange,提问作者Max Allan Jonathan Fotchin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 21:47:44