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

进程运行时在窗口中显示计时器的实现咨询(附Python脚本执行代码)

实现方案:Python脚本执行时显示窗口计时器

我来给你梳理一个可行的实现方案,核心是把Java的异步任务和窗口计时器结合起来——因为你的脚本执行是在单独线程里跑的,所以需要单独的UI组件来实时更新计时,同时监听脚本进程的结束状态来停止计时。下面是具体的实现步骤:

核心思路

  1. 用Swing(或JavaFX)做一个轻量窗口承载计时器显示
  2. 用Java的UI定时器(比如javax.swing.Timer)每秒更新计时数值
  3. 在脚本进程启动时开启计时器,进程结束后立刻停止计时并更新窗口状态

具体代码实现

第一步:封装计时器窗口类

先写一个独立的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:51:23