欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > JavaFX 实现 Loading 效果的组件与案例详解

JavaFX 实现 Loading 效果的组件与案例详解

2024/11/30 12:49:03 来源:https://blog.csdn.net/weixin_39996520/article/details/144014737  浏览:    关键词:JavaFX 实现 Loading 效果的组件与案例详解

JavaFX 中的 Loading 组件概述

JavaFX 提供了两个用于显示任务进度的核心组件:

  1. ProgressIndicator:以圆形动画的形式展示任务进度,适用于未定义进度的任务。
  2. ProgressBar:以水平条的形式展示任务进度,适用于可以量化进度的任务。

这两个组件可直接绑定到后台任务的 progress 属性,实时更新界面。

1. ProgressBar 的常见方法

ProgressBar 是以 水平条 的形式显示任务进度,适用于可量化的任务。

1.1 构造方法

  • ProgressBar()
    创建一个初始进度为 0 的进度条。
  • ProgressBar(double progress)
    创建一个指定初始进度的进度条。
    • 参数 progress:范围为 [0.0, 1.0],表示百分比进度。

1.2 常用方法

方法名说明示例
setProgress(double value)设置进度条的进度值。value 范围为 [0.0, 1.0],-1 表示不确定的进度(类似于加载动画)。progressBar.setProgress(0.5);
getProgress()获取当前进度条的进度值。double progress = progressBar.getProgress();
progressProperty()返回一个 DoubleProperty,可以用于绑定任务的进度属性。progressBar.progressProperty().bind(task.progressProperty());

1.3 样式方法

方法名说明示例
setStyle(String style)设置进度条的 CSS 样式。可以自定义进度条的外观。progressBar.setStyle("-fx-accent: green;");

1.4 使用示例

ProgressBar progressBar = new ProgressBar();
progressBar.setProgress(0.5); // 设置进度为50%
progressBar.setStyle("-fx-accent: blue;"); // 将进度条颜色设置为蓝色

2. ProgressIndicator 的常见方法

ProgressIndicator圆形动画 的形式显示任务进度,适用于未定义具体进度的任务(如等待加载)。

2.1 构造方法

  • ProgressIndicator()
    创建一个初始进度为 不确定状态 的指示器。
  • ProgressIndicator(double progress)
    创建一个指定初始进度的指示器。

2.2 常用方法

方法名说明示例
setProgress(double value)设置指示器的进度值,value 范围为 [0.0, 1.0],-1 表示不确定的进度状态(默认值)。progressIndicator.setProgress(-1);
getProgress()获取当前指示器的进度值。double progress = progressIndicator.getProgress();
progressProperty()返回一个 DoubleProperty,可以用于绑定任务的进度属性。progressIndicator.progressProperty().bind(task.progressProperty());

2.3 样式方法

方法名说明示例
setStyle(String style)设置指示器的 CSS 样式。可以自定义指示器的外观。progressIndicator.setStyle("-fx-accent: red;");

2.4 使用示例

ProgressIndicator progressIndicator = new ProgressIndicator();
progressIndicator.setProgress(-1); // 设置为不确定状态
progressIndicator.setStyle("-fx-accent: green;"); // 设置指示器颜色为绿色

3. 常见方法对比

功能ProgressBarProgressIndicator
表示形式水平条形进度圆形指示器
初始进度默认 0.0默认 -1(不确定进度)
绑定支持支持绑定任务的 progressProperty()支持绑定任务的 progressProperty()
适用场景可量化的任务进度未量化的任务(如加载等待)
进度状态进度条会逐步增长圆形动画逐步覆盖

4. 常见问题及解决方案

4.1 界面卡顿问题

问题原因:
在 JavaFX 中,所有 UI 更新都运行在单线程模式下。如果后台任务运行在 UI 线程,会导致界面卡顿。

解决方案:

  • 使用 Task 将后台任务与 UI 线程分离。
  • 确保耗时操作(如数据库查询)在 Taskcall 方法中执行。

4.2 动画流畅性问题

问题原因:
任务更新过于频繁,导致 UI 线程处理不过来。

解决方案:

  • 限制更新频率,例如每 10% 更新一次进度:
if (i % (NUM_TASKS / 10) == 0) {updateProgress(i, NUM_TASKS);
}

4.3 异常处理问题

问题原因:
任务执行时可能抛出异常,导致应用崩溃。

解决方案:

  • 在任务的 setOnFailed 方法中处理异常:
task.setOnFailed(event -> {Throwable exception = task.getException();System.err.println("Task failed: " + exception.getMessage());
});

4.4 停止任务

问题原因:
用户可能需要取消任务,但未正确处理会导致资源泄漏。

解决方案:

  • 使用 Taskcancel 方法并处理中断:
if (isCancelled()) {updateMessage("Task cancelled.");break;
}

5.完整案例示范

Maven 依赖

确保 JavaFX 的依赖正确引入(适配 JavaFX 21 和 JDK 8):

<dependencies><dependency><groupId>org.openjfx</groupId><artifactId>javafx-controls</artifactId><version>21</version></dependency><dependency><groupId>org.openjfx</groupId><artifactId>javafx-base</artifactId><version>21</version></dependency>
</dependencies>

核心代码

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ReloadableLoadingExample extends Application {private final ExecutorService threadPool = Executors.newFixedThreadPool(5);@Overridepublic void start(Stage primaryStage) {// 主界面组件ProgressBar progressBar = new ProgressBar(0);ProgressIndicator progressIndicator = new ProgressIndicator(0);Button startButton = new Button("Start Loading");Label statusLabel = new Label("Click 'Start Loading' to begin.");VBox content = new VBox(10, startButton, statusLabel, progressBar, progressIndicator);content.setStyle("-fx-padding: 20; -fx-alignment: center;");// 隐藏进度条和指示器progressBar.setVisible(false);progressIndicator.setVisible(false);// 遮罩层StackPane overlay = createOverlay(content);overlay.setVisible(false); // 默认隐藏遮罩层// 主界面StackPane root = new StackPane(content, overlay);Scene scene = new Scene(root, 400, 250);// 启动任务按钮startButton.setOnAction(event -> {// 禁用按钮,显示遮罩和进度条startButton.setDisable(true);overlay.setVisible(true);progressBar.setVisible(true);progressIndicator.setVisible(true);// 创建任务Task<Void> task = createLoadingTask(statusLabel);// 重置进度和状态progressBar.progressProperty().unbind();progressIndicator.progressProperty().unbind();progressBar.setProgress(0);progressIndicator.setProgress(0);// 绑定任务进度progressBar.progressProperty().bind(task.progressProperty());progressIndicator.progressProperty().bind(task.progressProperty());// 提交任务到线程池threadPool.submit(task);// 任务完成时的处理task.setOnSucceeded(e -> {overlay.setVisible(false);startButton.setDisable(false);progressBar.setVisible(false);progressIndicator.setVisible(false);showAlert(Alert.AlertType.INFORMATION, "Task Completed", "The task completed successfully!");});// 任务失败时的处理task.setOnFailed(e -> {overlay.setVisible(false);startButton.setDisable(false);progressBar.setVisible(false);progressIndicator.setVisible(false);showAlert(Alert.AlertType.ERROR, "Task Failed", "An error occurred: " + task.getException().getMessage());});// 任务取消时的处理task.setOnCancelled(e -> {overlay.setVisible(false);startButton.setDisable(false);progressBar.setVisible(false);progressIndicator.setVisible(false);showAlert(Alert.AlertType.WARNING, "Task Cancelled", "The task was cancelled.");});});primaryStage.setScene(scene);primaryStage.setTitle("Reloadable JavaFX Loading Example");primaryStage.show();}/*** 创建任务*/private Task<Void> createLoadingTask(Label statusLabel) {return new Task<Void>() {private static final int TOTAL_WORK = 100;@Overrideprotected Void call() throws Exception {for (int i = 1; i <= TOTAL_WORK; i++) {if (isCancelled()) {updateMessage("Task cancelled.");break;}// 模拟任务执行Thread.sleep(50);// 更新进度和状态updateProgress(i, TOTAL_WORK);updateMessage("Progress: " + i + "/" + TOTAL_WORK);}if (!isCancelled()) {updateMessage("Task completed successfully!");}return null;}@Overrideprotected void updateMessage(String message) {// 界面线程中更新状态javafx.application.Platform.runLater(() -> statusLabel.setText(message));}};}/*** 创建遮罩层*/private StackPane createOverlay(Region parent) {Rectangle overlayRectangle = new Rectangle();overlayRectangle.setFill(Color.rgb(0, 0, 0, 0.3));overlayRectangle.widthProperty().bind(parent.widthProperty());overlayRectangle.heightProperty().bind(parent.heightProperty());Label loadingLabel = new Label("Loading...");loadingLabel.setStyle("-fx-font-size: 16px; -fx-text-fill: white;");StackPane overlay = new StackPane(overlayRectangle, loadingLabel);overlay.setAlignment(Pos.CENTER);return overlay;}/*** 显示提示信息*/private void showAlert(Alert.AlertType alertType, String title, String content) {Alert alert = new Alert(alertType);alert.setTitle(title);alert.setContentText(content);alert.showAndWait();}@Overridepublic void stop() {threadPool.shutdownNow();}public static void main(String[] args) {launch(args);}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com