使用 javafx 创建一个从数字开始倒计时并在 0 播放音乐的程序
Creating a program that counts down from a number and plays music at 0 using javafx
正在尝试创建一个显示窗格的程序,用户可以在其中输入数字并按 Enter 键。
然后程序应每隔一秒从该数字开始倒计时。
一旦计数器达到 0,它应该播放声音。
我在让我的程序运行时遇到问题,并且不完全确定我在哪里搞砸了或者我做错了什么。
所以理论上,如果用户输入“30”,它应该开始倒数到 0,每次减一。 29 ... 28 ... 27 ... 等等
这是我的代码:
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);
}
}
编辑:在 运行 之后,我得到了这一长串错误:
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$launchApplication5(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$launchApplication11(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait5(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null3(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater4(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$null8(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
您的代码中有几个错误:
- 您正在读取文本字段并立即设置
countDown
,即在用户输入任何内容之前。当用户在文本字段上执行操作时,您需要阅读文本。
- 您将动画的循环计数设置为
INDEFINITE
而不是 countDown
的值
- 您设置了一次循环计数,而不是在用户提交文本字段时设置它
- 您将按钮的
onAction
属性 设置了两次。 onAction
只是一个 属性 和其他任何东西一样:如果你设置它然后再次设置它,它将只保存第二个值,即第一次调用 textField.setOnAction(...)
不会有任何效果。
- 文本字段上的第一个操作处理程序无论如何都不做任何事情:它将文本字段的文本设置为文本字段的当前文本。
你需要这样的东西:
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);
}
}
您可能还应该解决许多其他问题(例如,如果用户在动画正在进行时在文本字段上执行操作会发生什么,等等)但这至少会达到 "work".
正在尝试创建一个显示窗格的程序,用户可以在其中输入数字并按 Enter 键。
然后程序应每隔一秒从该数字开始倒计时。
一旦计数器达到 0,它应该播放声音。
我在让我的程序运行时遇到问题,并且不完全确定我在哪里搞砸了或者我做错了什么。
所以理论上,如果用户输入“30”,它应该开始倒数到 0,每次减一。 29 ... 28 ... 27 ... 等等
这是我的代码:
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);
}
}
编辑:在 运行 之后,我得到了这一长串错误:
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$launchApplication5(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$launchApplication11(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait5(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null3(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater4(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$null8(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
您的代码中有几个错误:
- 您正在读取文本字段并立即设置
countDown
,即在用户输入任何内容之前。当用户在文本字段上执行操作时,您需要阅读文本。 - 您将动画的循环计数设置为
INDEFINITE
而不是countDown
的值
- 您设置了一次循环计数,而不是在用户提交文本字段时设置它
- 您将按钮的
onAction
属性 设置了两次。onAction
只是一个 属性 和其他任何东西一样:如果你设置它然后再次设置它,它将只保存第二个值,即第一次调用textField.setOnAction(...)
不会有任何效果。 - 文本字段上的第一个操作处理程序无论如何都不做任何事情:它将文本字段的文本设置为文本字段的当前文本。
你需要这样的东西:
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);
}
}
您可能还应该解决许多其他问题(例如,如果用户在动画正在进行时在文本字段上执行操作会发生什么,等等)但这至少会达到 "work".