首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >JavaFX时钟小部件随机抛出异常

JavaFX时钟小部件随机抛出异常
EN

Stack Overflow用户
提问于 2016-02-26 11:34:19
回答 1查看 253关注 0票数 1

我编写了一个扩展Text类JavaFX的小时钟Widget。为了更新时间,我使用了一个基本上将文本设置为当前系统时间的Task。当我在Eclipse中运行这个应用程序时,它有时会在我称为NullpointerException的行中抛出一个stage.show()

这就是我的小部件源代码的样子:

代码语言:javascript
代码运行次数:0
运行
复制
package clock;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import javafx.concurrent.Task;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

public class CurrentClockText extends Text {
    private final DateTimeFormatter formatter;

    public static final int HOUR = 1;
    public static final int HOUR_MINUTE = 2;
    public static final int HOUR_MINUTE_SECOND = 3;
    public static final int HOUR_MINUTE_SECOND_MILLISECOND = 4;

    private final long updateInterval;

    private final Task<Void> updater = new Task<Void>() {
        @Override
        protected Void call() throws Exception {
            while (true) {
                LocalDateTime now = LocalDateTime.now();
                String nowTextual = formatter.format(now);
                setText(nowTextual);

                try {
                    Thread.sleep(updateInterval);
                } catch (InterruptedException ignore) {
                }
            }
        }
    };

    public CurrentClockText() {
        this(HOUR_MINUTE);
    }

    public CurrentClockText(final int detailLevel) {
        String timeFormat = "";
        switch (detailLevel) {
        case HOUR:
            timeFormat = "HH";
            updateInterval = 60000;
            break;
        case HOUR_MINUTE:
            timeFormat = "HH:mm";
            updateInterval = 15000;
            break;
        case HOUR_MINUTE_SECOND:
            timeFormat = "HH:mm:ss";
            updateInterval = 500;
            break;
        case HOUR_MINUTE_SECOND_MILLISECOND:
            updateInterval = 1;
            timeFormat = "HH:mm:ss.S";
            break;
        default:
            throw new IllegalArgumentException(
                    "Unknown detail level for Clock: " + detailLevel);
        }

        setFont(new Font("Verdana", 28));

        formatter = DateTimeFormatter.ofPattern(timeFormat);
        Thread updaterThread = new Thread(updater, "CurrentClockText.updaterThread");
        updaterThread.setDaemon(true);
        updaterThread.start();
    }
}

这是主要的课程:

代码语言:javascript
代码运行次数:0
运行
复制
package clock;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Boot extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        BorderPane pane = new BorderPane();

        CurrentClockText clock = new CurrentClockText(4);
        pane.setCenter(clock);

        Scene scene = new Scene(pane);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        Boot.launch(args);
    }

}

这就是堆栈轨迹:

代码语言:javascript
代码运行次数:0
运行
复制
Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$152(Unknown Source)
    at com.sun.javafx.application.LauncherImpl$$Lambda$50/14845382.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
    at com.sun.javafx.text.PrismTextLayout.addTextRun(Unknown Source)
    at com.sun.javafx.text.GlyphLayout.addTextRun(Unknown Source)
    at com.sun.javafx.text.GlyphLayout.breakRuns(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.buildRuns(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.layout(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.ensureLayout(Unknown Source)
    at com.sun.javafx.text.PrismTextLayout.getBounds(Unknown Source)
    at javafx.scene.text.Text.getLogicalBounds(Unknown Source)
    at javafx.scene.text.Text.impl_computeLayoutBounds(Unknown Source)
    at javafx.scene.Node$12.computeBounds(Unknown Source)
    at javafx.scene.Node$LazyBoundsProperty.get(Unknown Source)
    at javafx.scene.Node$LazyBoundsProperty.get(Unknown Source)
    at javafx.scene.Node.getLayoutBounds(Unknown Source)
    at javafx.scene.Node.prefWidth(Unknown Source)
    at javafx.scene.Node.minWidth(Unknown Source)
    at javafx.scene.layout.Region.computeChildPrefAreaWidth(Unknown Source)
    at javafx.scene.layout.BorderPane.getAreaWidth(Unknown Source)
    at javafx.scene.layout.BorderPane.computePrefWidth(Unknown Source)
    at javafx.scene.Parent.prefWidth(Unknown Source)
    at javafx.scene.layout.Region.prefWidth(Unknown Source)
    at javafx.scene.Scene.getPreferredWidth(Unknown Source)
    at javafx.scene.Scene.resizeRootToPreferredSize(Unknown Source)
    at javafx.scene.Scene.preferredSize(Unknown Source)
    at javafx.scene.Scene.impl_preferredSize(Unknown Source)
    at javafx.stage.Window$9.invalidated(Unknown Source)
    at javafx.beans.property.BooleanPropertyBase.markInvalid(Unknown Source)
    at javafx.beans.property.BooleanPropertyBase.set(Unknown Source)
    at javafx.stage.Window.setShowing(Unknown Source)
    at javafx.stage.Window.show(Unknown Source)
    at javafx.stage.Stage.show(Unknown Source)
    at clock.Boot.start(Boot.java:19)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(Unknown Source)
    at com.sun.javafx.application.LauncherImpl$$Lambda$53/19600960.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$45/18503843.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$170(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$48/27167109.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$47/2180324.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source)
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/3326003.run(Unknown Source)
    ... 1 more
Exception running application clock.Boot

正如我说过的,这种异常只发生在某些运行中,而不是总是发生。这种情况主要发生在我更改detailLevel = 4的格式模式时,但在再次更改它之后,它仍然需要另一次运行。我猜想这实际上可能与Eclipse有关,但我也无法调试代码,因为异常会抛出到stage.show调用中,我完全不明白这一点。造成这种随机异常的原因是什么,我如何解决它?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-26 12:27:26

在JavaFX中,和大多数其他GUI工具包一样,有一个特定的线程处理所有与UI相关的操作。应用程序不得在此线程之外更新UI。如果需要从另一个线程更新UI,通常可以使用API来确保代码在UI线程的上下文中执行。如果是JavaFX,有关更多信息,请参见JavaFX教程中的并发性

在您的情况下,最简单的解决方案是确保setText()调用在JavaFX应用程序线程上执行,而不是在与Task关联的线程上执行。

代码语言:javascript
代码运行次数:0
运行
复制
...
Platform.runLater(() -> setText(nowTextual));
...

JavaFX中还有其他API可用于动画,这些API可用于在特定时间间隔调用处理程序方法--这将从循环中删除Thread.sleep()调用。有关详细信息,请参阅时间线

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35650627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档