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并添加到面板中,窗口调整时会触发多次重绘,导致旧的文本框没有被移除,新的又被添加,最终出现重叠。
修复步骤
- 提前创建并缓存JTextField:在
TableRepresentation初始化时一次性创建所有文本框,而非每次重绘都新建。 - 重绘时只更新位置和大小:窗口调整时,仅修改已有文本框的位置、大小和字体,不创建新组件。
- 移除
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
相关产品推荐
相关产品推荐

