创建一个从数字倒计时的程序,并使用javafx在0播放音乐

时间:2021-07-23 14:11:57

Trying to create a program that displays a pane where a user inputs a number and press the Enter key.

尝试创建一个程序,显示用户输入数字的窗格,然后按Enter键。

The program should then count down from that number every one second.

然后程序应该每秒从该数字开始倒计时。

Once the counter reaches 0, it should play a sound.

一旦计数器达到0,它就应该发出声音。

I am having trouble getting my program to work, and not entirely sure where I have messed up or what I am doing wrong.

我无法让我的程序工作,并且不完全确定我搞砸了哪里或者我做错了什么。

So in theory, if the user put in "30" it should start counting down to 0, subtracting by one each time. 29 ... 28 ... 27 ... etc

所以理论上,如果用户输入“30”,它应该开始倒数到0,每次减1。 29 ...... 28 ...... 27 ......等等

Here's my code:

这是我的代码:

public class Counter extends Application {

    private static final String MEDIA_URL = "http://cs.armstrong.edu/liang/common/sample.mp4";
    private TextField text = new TextField();
    int countDown = Integer.parseInt(text.getText());

    @Override
    public void start(Stage primaryStage) {

        Media media = new Media(MEDIA_URL);
        MediaPlayer mediaPlayer = new MediaPlayer(media);


        // create a pane and add a TextField
        BorderPane pane = new BorderPane();
        pane.setCenter(text);
        text.setFont(Font.font("Times", 35));

        // create a new animation
        Timeline animation = new Timeline(
            new KeyFrame(Duration.millis(1000), e -> {
                if (countDown > 0) {
                    countDown--;
                    text.setText(Integer.toString(countDown));
                }
                else {
                    mediaPlayer.play();
                }
              }));
              animation.setCycleCount(Timeline.INDEFINITE);

        // create and register a handler
        text.setOnAction(e -> text.setText(text.getText()));
        text.setOnAction(e -> animation.play());

        // create a scene and place it in the stage
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String args[]) {

        Application.launch(args);

    }

}

EDIT: upon running, I get this long list of errors:

编辑:运行时,我得到这么长的错误列表:

Exception in Application constructor
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: Unable to construct Application instance: class Counter
    at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(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$148(Unknown Source)
    ... 1 more
Caused by: java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at java.lang.Integer.parseInt(Unknown Source)
    at Counter.<init>(Counter.java:18)
    ... 13 more
Exception running application Counter

1 个解决方案

#1


1  

You have several errors in your code:

您的代码中有几个错误:

  • You're reading the text field and setting countDown immediately, i.e. before the user has input anything. You need to read the text when the user executes the action on the text field.
  • 您正在读取文本字段并立即设置countDown,即在用户输入任何内容之前。当用户在文本字段上执行操作时,您需要阅读文本。

  • You're setting the cycle count of the animation to INDEFINITE instead of to the value of countDown
  • 您将动画的循环计数设置为INDEFINITE而不是countDown的值

  • You set the cycle count once, instead of setting it when the user commits the text field
  • 您可以设置一次循环计数,而不是在用户提交文本字段时设置它

  • You're setting the onAction property of the button twice. onAction is just a property like any other: if you set it and then set it again, it will hold only the second value, i.e. the first call to textField.setOnAction(...) won't have any effect.
  • 您正在设置按钮的onAction属性两次。 onAction只是一个属性,就像任何其他属性一样:如果你设置然后再设置它,它只会保存第二个值,即对textField.setOnAction(...)的第一次调用不会产生任何影响。

  • The first action handler on the text field doesn't do anything anyway: it sets the text of the text field to the current text of the text field.
  • 文本字段上的第一个操作处理程序无论如何都不执行任何操作:它将文本字段的文本设置为文本字段的当前文本。

You need something like this:

你需要这样的东西:

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Counter extends Application {

    private static final String MEDIA_URL = "http://cs.armstrong.edu/liang/common/sample.mp4";
    private TextField text = new TextField();
    int countDown;

    @Override
    public void start(Stage primaryStage) {

        Media media = new Media(MEDIA_URL);
        MediaPlayer mediaPlayer = new MediaPlayer(media);

        // create a pane and add a TextField
        BorderPane pane = new BorderPane();
        pane.setCenter(text);
        text.setFont(Font.font("Times", 35));

        // create a new animation
        Timeline animation = new Timeline(new KeyFrame(Duration.millis(1000), e -> {
            if (countDown > 0) {
                countDown--;
                text.setText(Integer.toString(countDown));
            } else {
                mediaPlayer.play();
            }
        }));

        // create and register a handler
        // text.setOnAction(e -> text.setText(text.getText()));
        text.setOnAction(e -> {
            countDown = Integer.parseInt(text.getText());
            animation.setCycleCount(countDown + 1);
            animation.play();
        });

        // create a scene and place it in the stage
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String args[]) {

        Application.launch(args);

    }

}

There are a bunch of other things you should probably address (e.g. what happens if the user commits an action on the text field while the animation is in progress, etc) but this will at least get it to "work".

您应该解决许多其他问题(例如,如果用户在动画进行过程中对文本字段进行操作时会发生什么情况等),但这至少会让它“工作”。

#1


1  

You have several errors in your code:

您的代码中有几个错误:

  • You're reading the text field and setting countDown immediately, i.e. before the user has input anything. You need to read the text when the user executes the action on the text field.
  • 您正在读取文本字段并立即设置countDown,即在用户输入任何内容之前。当用户在文本字段上执行操作时,您需要阅读文本。

  • You're setting the cycle count of the animation to INDEFINITE instead of to the value of countDown
  • 您将动画的循环计数设置为INDEFINITE而不是countDown的值

  • You set the cycle count once, instead of setting it when the user commits the text field
  • 您可以设置一次循环计数,而不是在用户提交文本字段时设置它

  • You're setting the onAction property of the button twice. onAction is just a property like any other: if you set it and then set it again, it will hold only the second value, i.e. the first call to textField.setOnAction(...) won't have any effect.
  • 您正在设置按钮的onAction属性两次。 onAction只是一个属性,就像任何其他属性一样:如果你设置然后再设置它,它只会保存第二个值,即对textField.setOnAction(...)的第一次调用不会产生任何影响。

  • The first action handler on the text field doesn't do anything anyway: it sets the text of the text field to the current text of the text field.
  • 文本字段上的第一个操作处理程序无论如何都不执行任何操作:它将文本字段的文本设置为文本字段的当前文本。

You need something like this:

你需要这样的东西:

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Counter extends Application {

    private static final String MEDIA_URL = "http://cs.armstrong.edu/liang/common/sample.mp4";
    private TextField text = new TextField();
    int countDown;

    @Override
    public void start(Stage primaryStage) {

        Media media = new Media(MEDIA_URL);
        MediaPlayer mediaPlayer = new MediaPlayer(media);

        // create a pane and add a TextField
        BorderPane pane = new BorderPane();
        pane.setCenter(text);
        text.setFont(Font.font("Times", 35));

        // create a new animation
        Timeline animation = new Timeline(new KeyFrame(Duration.millis(1000), e -> {
            if (countDown > 0) {
                countDown--;
                text.setText(Integer.toString(countDown));
            } else {
                mediaPlayer.play();
            }
        }));

        // create and register a handler
        // text.setOnAction(e -> text.setText(text.getText()));
        text.setOnAction(e -> {
            countDown = Integer.parseInt(text.getText());
            animation.setCycleCount(countDown + 1);
            animation.play();
        });

        // create a scene and place it in the stage
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String args[]) {

        Application.launch(args);

    }

}

There are a bunch of other things you should probably address (e.g. what happens if the user commits an action on the text field while the animation is in progress, etc) but this will at least get it to "work".

您应该解决许多其他问题(例如,如果用户在动画进行过程中对文本字段进行操作时会发生什么情况等),但这至少会让它“工作”。