Java Swing工件尺寸输入框问题排查与优化方案咨询
问题解决与优化方案
先解决你当前的两个核心问题
问题原因分析
你遇到的两个问题本质上是同一个逻辑顺序错误导致的:
在按钮点击事件中,你先执行了Integer.parseInt(),如果输入框为空,这个方法会直接抛出NumberFormatException,导致后续的空判断代码根本没机会运行,同时因为没有捕获这个异常,控制台就会输出大量错误栈信息。
修改后的按钮点击事件代码
btnPrfeDieAngaben.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // 先清空之前的提示 leeresFeld.setText(""); // 获取输入文本并去除首尾空格 String heightText = Feld1.getText().trim(); String widthText = Feld2.getText().trim(); String lengthText = Feld3.getText().trim(); // 优先检查是否有空输入 if (heightText.isEmpty() || widthText.isEmpty() || lengthText.isEmpty()) { leeresFeld.setText("Please fill in all fields!"); return; } int answer1, answer2, answer3; try { // 安全解析数字(加兜底异常捕获) answer1 = Integer.parseInt(heightText); answer2 = Integer.parseInt(widthText); answer3 = Integer.parseInt(lengthText); } catch (NumberFormatException ex) { // 理论上因按键过滤不会走到这里,但留个兜底逻辑 leeresFeld.setText("Please enter valid numbers only!"); return; } // 检查数值范围 if (answer1 >= 1 && answer1 <= 150 && answer2 >= 1 && answer2 <= 150 && answer3 >= 1 && answer3 <= 150) { leeresFeld.setText("You entered: " + heightText + " , " + widthText + " , " + lengthText + " mm"); } else { ImageIcon iconic = new ImageIcon(Machine_LearningApp.class.getResource("x-taste.png")); // 改用WARNING_MESSAGE更符合警告场景 JOptionPane.showMessageDialog(null, "Enter only numbers between 1 and 150 mm!", "Warning", JOptionPane.WARNING_MESSAGE, iconic); } } });
更优实现方式建议
除了修复当前问题,还有几个可以提升代码质量和用户体验的优化点:
1. 替换Null布局为布局管理器
你现在用的setLayout(null)+手动设置bounds的方式,会导致界面在不同分辨率、窗口大小变化时完全错乱。推荐使用BorderLayout、GridBagLayout或者GroupLayout,结合JPanel嵌套不同布局,让界面自适应各种场景。
2. 复用重复的按键监听逻辑
三个输入框的按键监听代码完全一致,可以提取成单独实例避免重复:
KeyAdapter numberKeyAdapter = new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { char c = e.getKeyChar(); if (!(Character.isDigit(c) || c == KeyEvent.VK_BACK_SPACE || c == KeyEvent.VK_DELETE)) { e.consume(); } } @Override public void keyReleased(KeyEvent e) { leeresFeld.setText(""); // 直接清空比设空格更合理 } }; // 给三个输入框绑定同一个监听 Feld1.addKeyListener(numberKeyAdapter); Feld2.addKeyListener(numberKeyAdapter); Feld3.addKeyListener(numberKeyAdapter);
3. 使用InputVerifier实现即时输入验证
相比在按钮点击时统一验证,InputVerifier可以在用户离开输入框时即时提示错误,提升用户体验:
InputVerifier numberRangeVerifier = new InputVerifier() { @Override public boolean verify(JComponent input) { JTextField tf = (JTextField) input; String text = tf.getText().trim(); if (text.isEmpty()) { leeresFeld.setText("This field cannot be empty!"); return false; } try { int num = Integer.parseInt(text); if (num < 1 || num > 150) { leeresFeld.setText("Please enter a number between 1 and 150!"); return false; } } catch (NumberFormatException ex) { leeresFeld.setText("Please enter a valid number!"); return false; } leeresFeld.setText(""); return true; } }; // 绑定到输入框 Feld1.setInputVerifier(numberRangeVerifier); Feld2.setInputVerifier(numberRangeVerifier); Feld3.setInputVerifier(numberRangeVerifier);
4. 使用DocumentFilter彻底限制输入内容
按键监听无法阻止用户通过粘贴输入非数字,DocumentFilter可以从根本上限制文本框只能输入数字:
class NumberDocumentFilter extends DocumentFilter { @Override public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { if (string.matches("\\d*")) { // 只允许输入数字 super.insertString(fb, offset, string, attr); } } @Override public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException { if (text.matches("\\d*")) { super.replace(fb, offset, length, text, attrs); } } } // 给输入框设置过滤器 ((AbstractDocument) Feld1.getDocument()).setDocumentFilter(new NumberDocumentFilter()); ((AbstractDocument) Feld2.getDocument()).setDocumentFilter(new NumberDocumentFilter()); ((AbstractDocument) Feld3.getDocument()).setDocumentFilter(new NumberDocumentFilter());
5. 组件命名规范化
把Feld1、Feld2改成heightField、widthField这类有语义的名称,代码可读性和维护性会大幅提升。
内容的提问来源于stack exchange,提问作者f_ozk
相关产品推荐
相关产品推荐

