进程运行时在窗口中显示计时器的实现咨询(附Python脚本执行代码)
实现方案:Python脚本执行时显示窗口计时器
我来给你梳理一个可行的实现方案,核心是把Java的异步任务和窗口计时器结合起来——因为你的脚本执行是在单独线程里跑的,所以需要单独的UI组件来实时更新计时,同时监听脚本进程的结束状态来停止计时。下面是具体的实现步骤:
核心思路
- 用Swing(或JavaFX)做一个轻量窗口承载计时器显示
- 用Java的UI定时器(比如
javax.swing.Timer)每秒更新计时数值 - 在脚本进程启动时开启计时器,进程结束后立刻停止计时并更新窗口状态
具体代码实现
第一步:封装计时器窗口类
先写一个独立的Swing窗口类,专门处理计时器的显示和控制逻辑:
import javax.swing.*; import java.awt.*; public class ExecutionTimerWindow extends JFrame { private JLabel timerDisplay; private int elapsedSeconds = 0; private Timer updateTimer; public ExecutionTimerWindow() { // 窗口基础配置 setTitle("脚本执行中,请稍候..."); setSize(320, 160); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 防止用户中途关闭 setLocationRelativeTo(null); // 窗口居中 // 计时标签样式 timerDisplay = new JLabel("已耗时: 0 秒", SwingConstants.CENTER); timerDisplay.setFont(new Font("微软雅黑", Font.PLAIN, 22)); add(timerDisplay, BorderLayout.CENTER); // 初始化每秒更新的定时器 updateTimer = new Timer(1000, e -> { elapsedSeconds++; timerDisplay.setText("已耗时: " + elapsedSeconds + " 秒"); }); } // 启动计时器并显示窗口 public void start() { updateTimer.start(); setVisible(true); } // 停止计时器并更新完成提示 public void stop() { updateTimer.stop(); timerDisplay.setText("脚本执行完成!总耗时: " + elapsedSeconds + " 秒"); // 可选:2秒后自动关闭窗口 new Timer(2000, e -> dispose()).start(); } }
第二步:修改原Python执行方法
把计时器窗口集成到你的executePythonScriptWithArgs方法里,关键是在进程启动后开启计时,进程结束后停止计时:
import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import javax.swing.SwingUtilities; public class PythonScriptRunner { private boolean executionSuccess = false; public boolean executePythonScriptWithArgs(File file, String args) { ExecutionTimerWindow timerWindow = new ExecutionTimerWindow(); Runnable scriptTask = () -> { Process pythonProcess = null; try { // 启动Python脚本进程 pythonProcess = Runtime.getRuntime().exec("python3 " + file.getPath() + " " + args); BufferedReader inputReader = new BufferedReader(new InputStreamReader(pythonProcess.getInputStream())); // 在Swing事件线程中启动计时器(必须保证UI操作线程安全) SwingUtilities.invokeLater(timerWindow::start); // 读取Python脚本输出,判断执行结果 String outputLine; while ((outputLine = inputReader.readLine()) != null) { if (outputLine.equals("success")) { executionSuccess = true; } // 可选:把Python输出打印到控制台 System.out.println("Python脚本输出: " + outputLine); } // 等待脚本进程完全结束 int exitCode = pythonProcess.waitFor(); System.out.println("脚本退出码: " + exitCode); } catch (Exception e) { e.printStackTrace(); executionSuccess = false; } finally { // 释放进程资源 if (pythonProcess != null) { pythonProcess.destroy(); } // 在Swing事件线程中停止计时器 SwingUtilities.invokeLater(timerWindow::stop); } }; // 启动单独线程执行脚本,避免阻塞UI new Thread(scriptTask).start(); // 注意:如果需要同步等待脚本执行结果,这里可以用CountDownLatch实现,否则返回的是初始值(异步场景) return executionSuccess; } // 测试用例 public static void main(String[] args) { new PythonScriptRunner().executePythonScriptWithArgs(new File("test_script.py"), "arg1 arg2"); } }
关键注意事项
- Swing线程安全:所有更新UI组件的操作必须放在Swing事件调度线程(EDT)中执行,所以用
SwingUtilities.invokeLater包裹计时器的启动/停止逻辑,避免UI卡顿或异常。 - 进程资源释放:在
finally块中调用pythonProcess.destroy(),确保脚本进程被正确销毁,防止资源泄漏。 - 同步/异步选择:原方法是异步执行脚本,如果需要等待脚本完成后再返回结果,可以用
CountDownLatch实现同步,比如在脚本任务中调用latch.countDown(),然后在主方法中调用latch.await()等待。 - 窗口关闭控制:设置
DO_NOTHING_ON_CLOSE是为了防止用户中途关闭窗口导致计时中断,如果允许用户手动关闭,可以改成DISPOSE_ON_CLOSE,但要注意脚本可能还在后台运行。
替代方案(JavaFX场景)
如果你的应用是基于JavaFX开发的,可以用javafx.animation.Timeline实现计时器,逻辑和Swing版本类似:
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import javafx.util.Duration; import javafx.animation.KeyFrame; import javafx.animation.Timeline; public class FXTimerWindow extends Application { private int elapsedSeconds = 0; private Label timerLabel = new Label("已耗时: 0 秒"); private Timeline timeline; @Override public void start(Stage stage) { timeline = new Timeline(new KeyFrame(Duration.seconds(1), e -> { elapsedSeconds++; timerLabel.setText("已耗时: " + elapsedSeconds + " 秒"); })); timeline.setCycleCount(Timeline.INDEFINITE); StackPane root = new StackPane(timerLabel); Scene scene = new Scene(root, 320, 160); stage.setTitle("脚本执行中..."); stage.setScene(scene); stage.show(); timeline.play(); } public void stopTimer() { timeline.stop(); timerLabel.setText("脚本执行完成!总耗时: " + elapsedSeconds + " 秒"); } }
在Java代码中启动JavaFX应用时,同样要注意线程安全,确保UI操作在JavaFX应用线程中执行。
内容的提问来源于stack exchange,提问作者madcrazydrumma
相关产品推荐
相关产品推荐

