Java中JOptionPane.showInputDialog触发次数异常的原因与解决办法
解决Swing条形图输入对话框重复弹出的问题
嘿,我来帮你搞定这个问题!你遇到的输入对话框持续弹出的问题,核心原因是你把用户输入的逻辑放在了paintComponent方法里,而这个方法的执行时机完全由Swing的渲染机制控制,不是你能直接掌控的。
为什么会重复弹出?
paintComponent是Swing用来绘制组件的核心方法,它会在很多场景下被自动调用:
- 窗口第一次显示的时候
- 窗口大小被调整的时候
- 窗口从最小化状态恢复的时候
- 窗口被其他窗口挡住后重新显示的时候
- 甚至系统偶尔也会触发重绘请求
你把输入对话框和do-while循环放在这个方法里,就意味着每次Swing需要重绘你的面板时,这段代码都会重新执行一遍——哪怕你已经输入完所有条形的长度了,只要窗口触发重绘,对话框就会再次弹出来。
解决方案:分离输入逻辑和绘制逻辑
正确的做法是把用户输入的操作放在程序初始化阶段完成,先收集好所有条形的长度,然后让paintComponent只负责根据已有的数据绘制条形,不要再在里面处理任何用户交互。
下面是修改后的完整代码:
修改后的Bar类(只负责绘制)
import java.awt.Graphics; import javax.swing.JPanel; public class Bar extends JPanel { private int[] barLengths; // 存储所有条形的长度 // 构造方法接收预先收集好的条形长度数组 public Bar(int[] barLengths) { this.barLengths = barLengths; } @Override public void paintComponent(Graphics g) { super.paintComponent(g); // 遍历数组,绘制每个条形 for (int i = 0; i < barLengths.length; i++) { int length = barLengths[i]; // 绘制对应长度的条形(位置按索引递增) g.drawRect(0, 5 + i * 20, length * 15, 15); } } }
修改后的ShapesExercise主类(负责输入和初始化)
import javax.swing.JFrame; import javax.swing.JOptionPane; public class ShapesExercise { public static void main(String[] args) { int noOfBars = 0; // 第一步:获取有效的条形总数(添加输入验证) while (true) { String input = JOptionPane.showInputDialog("Enter total bars to display:"); try { noOfBars = Integer.parseInt(input); if (noOfBars > 0) { break; // 输入有效,退出循环 } else { JOptionPane.showMessageDialog(null, "请输入一个正整数哦!"); } } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "输入无效,请输入整数!"); } } // 第二步:收集每个条形的长度 int[] barLengths = new int[noOfBars]; for (int i = 0; i < noOfBars; i++) { while (true) { String lengthInput = JOptionPane.showInputDialog("Enter length for bar " + (i + 1) + ":"); try { barLengths[i] = Integer.parseInt(lengthInput); if (barLengths[i] >= 0) { // 允许长度为0,可根据需求改为>0 break; } else { JOptionPane.showMessageDialog(null, "请输入非负整数!"); } } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "输入无效,请输入整数!"); } } } // 第三步:创建窗口和面板,显示图形 JFrame application = new JFrame(); application.setSize(300, 40 + 25 * noOfBars); Bar panel = new Bar(barLengths); application.add(panel); application.setVisible(true); application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
关键修改说明
- 分离职责:主类负责收集用户输入,Bar类只负责绘制图形,符合单一职责原则。
- 输入验证:添加了循环验证,处理非整数、负数等无效输入,让程序更健壮。
- 避免重复触发:
paintComponent现在只做绘制操作,不会再触发输入对话框,哪怕窗口被重绘也只会重新绘制已有的条形。
另外要记住:Swing的绘制方法(比如paintComponent)应该保持轻量化,只做和绘制相关的事情,不要在里面做用户交互、IO操作或者其他耗时任务,否则不仅会导致类似的重复触发问题,还会影响界面的响应速度。
内容的提问来源于stack exchange,提问作者Alexandru Cozmanca
相关产品推荐
相关产品推荐

