ffmpeg 代码实现捕获桌面_JavaFX桌面应用loading界面

上次使用JavaFX开发了一个视频转码工具,当用户点击“启动”按钮开始转码的时候,会禁用启动按钮,防止多次启动转码。

这种处理方式对用户来说可能并是很友好,其实可以在启动转码的时弹出一个loading界面,告诉用户正在进行视频转码。

重新改造一下之前的转码程序,使用loading界面提示用户视频正在转码,如图:

f43aa31f8f0d52d91c11ba79e1f91d25.png

针对这种通用的loading界面,可以使用JavaFX的stage开发一个通用的组件。

这里需要注意的是:

  1. loading界面没有边框的

  2. loading界面背景是透明的

  3. loading附着于主Stage

针对以上三点,可以分别设置loading stage的样式及模式:

// 设置stage无任何装饰stage.initStyle(StageStyle.UNDECORATED);// 设置stage背景透明stage.initStyle(StageStyle.TRANSPARENT);// 设置stage的模式stage.initModality(Modality.APPLICATION_MODAL);

loading界面由两部分组成,分别是loading动画(ProgressIndicator)和提示信息(Label),如下图:

7931432327b98e9fc4ae074315088c2f.png

所以可以采用VBox来布局(这里直接采用Java代码布局,不采用fxml):

// messageLabel adLbl = new Label(ad);adLbl.setTextFill(Color.BLUE);// progressProgressIndicator indicator = new ProgressIndicator();indicator.setProgress(-1);indicator.progressProperty().bind(work.progressProperty());// packVBox vBox = new VBox();vBox.setSpacing(10);vBox.setBackground(Background.EMPTY);vBox.getChildren().addAll(indicator, adLbl);

对于loading界面的宽度可以通过信息来计算,而loading界面的位置则设置为主stage的中心。

stage.setWidth(ad.length() * 8 + 10);stage.setHeight(100);// show center of parentdouble x = parent.getX() + (parent.getWidth() - stage.getWidth()) / 2;double y = parent.getY() + (parent.getHeight() - stage.getHeight()) / 2;stage.setX(x);stage.setY(y);

完整的loading界面代码如下:

/** * @author itqn */public class ProgressStage {    private Stage stage;    private Task> work;    private ProgressStage() {    }    /**     * 创建     *     * @param parent     * @param work     * @param ad     * @return     */    public static ProgressStage of(Stage parent, Task> work, String ad) {        ProgressStage ps = new ProgressStage();        ps.work = Objects.requireNonNull(work);        ps.initUI(parent, ad);        return ps;    }    /**     * 显示     */    public void show() {        new Thread(work).start();        stage.show();    }    private void initUI(Stage parent, String ad) {        stage = new Stage();        stage.initOwner(parent);        // style        stage.initStyle(StageStyle.UNDECORATED);        stage.initStyle(StageStyle.TRANSPARENT);        stage.initModality(Modality.APPLICATION_MODAL);        // message        Label adLbl = new Label(ad);        adLbl.setTextFill(Color.BLUE);        // progress        ProgressIndicator indicator = new ProgressIndicator();        indicator.setProgress(-1);        indicator.progressProperty().bind(work.progressProperty());        // pack        VBox vBox = new VBox();        vBox.setSpacing(10);        vBox.setBackground(Background.EMPTY);        vBox.getChildren().addAll(indicator, adLbl);        // scene        Scene scene = new Scene(vBox);        scene.setFill(null);        stage.setScene(scene);        stage.setWidth(ad.length() * 8 + 10);        stage.setHeight(100);        // show center of parent        double x = parent.getX() + (parent.getWidth() - stage.getWidth()) / 2;        double y = parent.getY() + (parent.getHeight() - stage.getHeight()) / 2;        stage.setX(x);        stage.setY(y);        // close if work finish        work.setOnSucceeded(e -> stage.close());    }}

loading动画跟Task任务的进度绑定,当Task完成的时候,关闭loading界面。这样loading界面组件就完成了。

接下来,改造之前的视频转码工具代码,将视频转码的代码改为继承Task,而不是Thread,这里Task不需要返回任何信息,所以泛型采用Void即可,然后重写call方法,将耗时的业务代码放在call中执行。

public class VideoConvertWork extends Task {    private String ffmpeg;    private List modelList;    private Consumer consumer;    public VideoConvertWork(String ffmpeg, List modelList, Consumer consumer) {        this.ffmpeg = ffmpeg;        this.modelList = modelList;        this.consumer = consumer;    }    @Override    protected Void call() throws Exception {        while (true) {            Optional opt = modelList.stream().filter(i -> !VideoConvertHolder.has(i.getId())).findFirst();            if (opt.isPresent()) {                try {                    VideoConvertHolder.add(opt.get().getId());                    convert(opt.get());                } catch (Exception e) {                    e.printStackTrace();                    Platform.runLater(() -> opt.get().setMessage(e.getMessage()));                }            } else {                break;            }        }        return null;    }}

调整“启动”按钮的事件处理:

public void executeConvertHandler(ActionEvent actionEvent) {    if (model.getTableList().isEmpty()) {        new Alert(Alert.AlertType.INFORMATION, "没有转码任务,请选择视频进行转码。").show();        return;    }    if (ffmpeg == null) {        new Alert(Alert.AlertType.ERROR, "FFmpeg.exe Not Found.").show();        return;    }//        ((Button) actionEvent.getSource()).setDisable(true);//        new VideoConvertExecutor(ffmpeg, model.getTableList(), s -> Platform.runLater(() -> model.setInfo(s))).start();    ProgressStage.of(        App.stage,        new VideoConvertWork(ffmpeg, model.getTableList(), s -> Platform.runLater(() -> model.setInfo(s))),        "视频转码中..."    ).show();}

loading界面作为通用的组件可以在任何耗时的业务场景下使用,只要将耗时的业务放在Task的call方法中执行即可。

推荐阅读:

JavaFX桌面应用开发-HelloWorld JavaFX布局神器-SceneBuilder JavaFX让UI更美观-CSS样式 JavaFX桌面应用-为什么应用老是“未响应” JavaFX桌面应用-MVC模式开发,“真香” JavaFX桌面应用-视频转码工具
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值