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

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);
    }
}

关键修改说明

  1. 分离职责:主类负责收集用户输入,Bar类只负责绘制图形,符合单一职责原则。
  2. 输入验证:添加了循环验证,处理非整数、负数等无效输入,让程序更健壮。
  3. 避免重复触发:paintComponent现在只做绘制操作,不会再触发输入对话框,哪怕窗口被重绘也只会重新绘制已有的条形。

另外要记住:Swing的绘制方法(比如paintComponent)应该保持轻量化,只做和绘制相关的事情,不要在里面做用户交互、IO操作或者其他耗时任务,否则不仅会导致类似的重复触发问题,还会影响界面的响应速度。

内容的提问来源于stack exchange,提问作者Alexandru Cozmanca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:05:29