
swing 是单线程 gui 框架,所有界面更新和事件处理必须在事件分发线程(edt)中执行;若在 actionperformed 中使用死循环(如 while(framerunning)),会彻底阻塞 edt,导致界面无响应、假死。正确做法是使用 swing timer 实现非阻塞的周期性检查与更新。
在你的代码中,actionPerformed 方法内启动了一个无限 while 循环:
framerunning = true;
// ... 创建 frame
while (framerunning) {
heightdyn = (int) heightinp.getValue();
widthdyn = (int) widthinp.getValue();
if (height != heightdyn || width != widthdyn) {
frame.setSize(widthdyn, heightdyn);
height = heightdyn;
width = widthdyn;
}
}该循环没有退出条件(framerunning 始终为 true),且运行在 Swing 的事件分发线程(EDT)上 —— 这会导致整个 UI 线程被卡死:按钮无法点击、输入框无法编辑、窗口无法拖动或重绘,即“应用停止工作”。
✅ 正确解决方案:用 javax.swing.Timer 替代 while 循环
Timer 是 Swing 提供的线程安全定时器,其回调 ActionListener 仍在 EDT 中执行,但不会阻塞主线程,可安全用于动态更新组件。
以下是关键修复步骤(仅需修改 actionPerformed 方法):
✅ 修复后的 actionPerformed 示例:
private Timer resizeTimer;
private JFrame dynamicFrame;
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == newframebutton) {
// 1. 创建新窗口
dynamicFrame = new JFrame("Dynamic Frame");
dynamicFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
dynamicFrame.setBackground(Color.LIGHT_GRAY);
dynamicFrame.setLocationRelativeTo(this);
// 2. 初始化尺寸
height = (int) heightinp.getValue();
width = (int) widthinp.getValue();
dynamicFrame.setSize(width, height);
dynamicFrame.setVisible(true);
// 3. 启动定时器(每 100ms 检查一次尺寸变化)
if (resizeTimer != null && resizeTimer.isRunning()) {
resizeTimer.stop();
}
resizeTimer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
int newHeight = (int) heightinp.getValue();
int newWidth = (int) widthinp.getValue();
if (newHeight != height || newWidth != width) {
height = newHeight;
width = newWidth;
dynamicFrame.setSize(width, height);
// 可选:自动调整位置以保持居中(提升体验)
dynamicFrame.setLocationRelativeTo(Frame.this);
}
}
});
resizeTimer.start();
}
}⚠️ 注意事项:
- 不要手动修改 framerunning:Timer 通过 stop() 控制生命周期,无需布尔标志。
-
及时清理资源:当 dynamicFrame 关闭时,应自动停止 Timer(可在 dynamicFrame.addWindowListener(...) 中添加 windowClosed 处理):
dynamicFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { if (resizeTimer != null) resizeTimer.stop(); } }); - 避免高频刷新:Timer 间隔建议 ≥ 50ms;过短(如 10ms)可能引发性能抖动,过长(如 500ms)则响应滞后。
- 禁止在 Timer 中执行耗时操作:例如文件读写、网络请求 —— 若必须,请用 SwingWorker 异步处理并安全回调更新 UI。
✅ 额外优化建议:
- 使用 JSpinner 的 ChangeListener 替代轮询(更高效、更符合 Swing 设计范式):
modelheight.addChangeListener(e -> updateDynamicFrame()); modelwidth.addChangeListener(e -> updateDynamicFrame());
然后将尺寸同步逻辑封装到 updateDynamicFrame() 方法中,并在其中判断 dynamicFrame != null && dynamicFrame.isVisible() 再执行 setSize。
总之,Swing 的核心原则是:永不阻塞事件分发线程。任何需要“持续监听”或“周期性更新”的场景,都应优先选用 Swing Timer、PropertyChangeListener 或响应式绑定(如 BindingGroup),而非裸 while 循环。










