在 Java 的 while 循环中创建场景时出现问题
Problem creating a scene in a while loop in Java
我想做的是:当程序启动时,用户需要输入一个数字。当数字为1时,进入一个矩形图形循环。矩形 stacks() 的图形将出现在屏幕上。然后,用户需要关闭图形(场景),程序再次要求用户输入。如果用户回答 1,矩形图形将再次出现,依此类推,直到用户给出 1 以外的答案。我的问题是,当我插入输入“1”时,矩形图形不会出现,而显示矩形图形的 window 是未响应。另外,当我在程序的开头给出 1 以外的答案时,我认为程序会以 "Process finished with exit code 0" 结束,但事实并非如此。我只能用 'stop' 按钮强制停止它。谁能帮我?谢谢。
package sample;
import java.io.*;
import java.util.*;
import javafx.application.Application;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.Scene;
import static javafx.scene.paint.Color.BLUE;
import static javafx.scene.paint.Color.RED;
public class Main extends Application{
@Override
public void start (Stage primaryStage) throws Exception
{
System.out.println("Enter a number: ");
Scanner scanner = new Scanner(System. in);
int xx = scanner.nextInt();
while(xx==1)
{
Rectangle rectangle;
ArrayList<Boolean> bool = new ArrayList<Boolean>();
AnchorPane root = new AnchorPane();
for(int i=0; i<10; i++)
{
if(i%2 ==0)
bool.add(true);
else
bool.add(false);
}
//Coordinate variables
int y=50;
//Rectangle loop
for(int i=0; i<10; i++)
{
rectangle = new Rectangle();
if(bool.get(i))
{
rectangle.setX(50);
rectangle.setY(y);
rectangle.setWidth(150.0);
rectangle.setHeight(50.0);
rectangle.setFill(RED);
}
else
{
rectangle.setX(50);
rectangle.setY(y);
rectangle.setWidth(150.0);
rectangle.setHeight(50.0);
rectangle.setFill(BLUE);
}
y+=50;
root.getChildren().add(rectangle);
}
primaryStage.setTitle("Rectangle");
Scene scene = new Scene(root ,600, 700);
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setResizable(false);
xx=scanner.nextInt();
}
}
public static void main (String[] args)
{
launch(args);
}
}
您是否尝试过在需要时使用 Platform.exit() 来完成程序?
使用 xx==1
进入循环后,您的屏幕应该可见。但是,您会看到 not responding
屏幕,因为在循环内部,您要求用户再次提供输入。所以在绘制矩形后,屏幕会冻结。如果您再次在屏幕上输入 1
,同样的事情会发生,因为相同的循环执行并返回到同一行要求输入。为清楚起见,在循环内询问 nextInt
时添加 Enter another number
。
一个可能的解决方案是提供一种中断循环并请求 nextInt
外部循环的方法。
为了验证这一点,当您的屏幕在第一次输入 1
后冻结(然后它要求从循环中输入另一个条目)时,您可以输入除 1
以外的任何内容来中断循环(例如0).所以你的屏幕现在应该有反应了,你的应用程序终止了。
这里有 2 个问题:
- 您不得阻塞 JavaFX 应用程序线程。在该线程上执行的方法(如
Application.start
)需要在短时间内 return 才能使 GUI 保持响应。如果您想继续使用 System.in
(我不推荐),您需要为循环使用单独的线程。
- 关闭最后阶段将默认自动关闭JavaFX。这可以使用
Platform.setImplicitExit()
修复
@Override
public void start(Stage primaryStage) throws Exception {
// don't automatically shutdown toolkit on window close
Platform.setImplicitExit(false);
primaryStage.setTitle("Rectangle");
AnchorPane root = new AnchorPane();
Scene scene = new Scene(root, 600, 700);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
// semaphore for synchronizing the closing
final Semaphore semaphore = new Semaphore(1);
// notify loop of window being closed
primaryStage.setOnHidden(evt -> semaphore.release());
final Scanner scanner = new Scanner(System.in);
System.out.println("Enter a number: ");
Runnable runnable = () -> {
while (true) {
// wait for window to be closed
try {
semaphore.acquire();
} catch (InterruptedException ex) {
return;
}
// read number
int xx = scanner.nextInt();
if (xx == 1) {
ArrayList<Boolean> bool = new ArrayList<>();
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
bool.add(true);
} else {
bool.add(false);
}
}
//Coordinate variables
int y = 50;
Node[] children = new Node[bool.size()];
//Rectangle loop
for (int i = 0; i < children.length; i++) {
Rectangle rectangle = new Rectangle(50, y, 150.0, 50.0);
rectangle.setFill(bool.get(i) ? RED : BLUE);
y += 50;
children[i] = rectangle;
}
// update gui
Platform.runLater(() -> {
root.getChildren().setAll(children);
primaryStage.show();
});
} else {
// shutdown javafx
Platform.exit();
break;
}
}
};
new Thread(runnable).start();
}
我想做的是:当程序启动时,用户需要输入一个数字。当数字为1时,进入一个矩形图形循环。矩形 stacks() 的图形将出现在屏幕上。然后,用户需要关闭图形(场景),程序再次要求用户输入。如果用户回答 1,矩形图形将再次出现,依此类推,直到用户给出 1 以外的答案。我的问题是,当我插入输入“1”时,矩形图形不会出现,而显示矩形图形的 window 是未响应。另外,当我在程序的开头给出 1 以外的答案时,我认为程序会以 "Process finished with exit code 0" 结束,但事实并非如此。我只能用 'stop' 按钮强制停止它。谁能帮我?谢谢。
package sample;
import java.io.*;
import java.util.*;
import javafx.application.Application;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.Scene;
import static javafx.scene.paint.Color.BLUE;
import static javafx.scene.paint.Color.RED;
public class Main extends Application{
@Override
public void start (Stage primaryStage) throws Exception
{
System.out.println("Enter a number: ");
Scanner scanner = new Scanner(System. in);
int xx = scanner.nextInt();
while(xx==1)
{
Rectangle rectangle;
ArrayList<Boolean> bool = new ArrayList<Boolean>();
AnchorPane root = new AnchorPane();
for(int i=0; i<10; i++)
{
if(i%2 ==0)
bool.add(true);
else
bool.add(false);
}
//Coordinate variables
int y=50;
//Rectangle loop
for(int i=0; i<10; i++)
{
rectangle = new Rectangle();
if(bool.get(i))
{
rectangle.setX(50);
rectangle.setY(y);
rectangle.setWidth(150.0);
rectangle.setHeight(50.0);
rectangle.setFill(RED);
}
else
{
rectangle.setX(50);
rectangle.setY(y);
rectangle.setWidth(150.0);
rectangle.setHeight(50.0);
rectangle.setFill(BLUE);
}
y+=50;
root.getChildren().add(rectangle);
}
primaryStage.setTitle("Rectangle");
Scene scene = new Scene(root ,600, 700);
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setResizable(false);
xx=scanner.nextInt();
}
}
public static void main (String[] args)
{
launch(args);
}
}
您是否尝试过在需要时使用 Platform.exit() 来完成程序?
使用 xx==1
进入循环后,您的屏幕应该可见。但是,您会看到 not responding
屏幕,因为在循环内部,您要求用户再次提供输入。所以在绘制矩形后,屏幕会冻结。如果您再次在屏幕上输入 1
,同样的事情会发生,因为相同的循环执行并返回到同一行要求输入。为清楚起见,在循环内询问 nextInt
时添加 Enter another number
。
一个可能的解决方案是提供一种中断循环并请求 nextInt
外部循环的方法。
为了验证这一点,当您的屏幕在第一次输入 1
后冻结(然后它要求从循环中输入另一个条目)时,您可以输入除 1
以外的任何内容来中断循环(例如0).所以你的屏幕现在应该有反应了,你的应用程序终止了。
这里有 2 个问题:
- 您不得阻塞 JavaFX 应用程序线程。在该线程上执行的方法(如
Application.start
)需要在短时间内 return 才能使 GUI 保持响应。如果您想继续使用System.in
(我不推荐),您需要为循环使用单独的线程。 - 关闭最后阶段将默认自动关闭JavaFX。这可以使用
Platform.setImplicitExit()
修复
@Override
public void start(Stage primaryStage) throws Exception {
// don't automatically shutdown toolkit on window close
Platform.setImplicitExit(false);
primaryStage.setTitle("Rectangle");
AnchorPane root = new AnchorPane();
Scene scene = new Scene(root, 600, 700);
primaryStage.setScene(scene);
primaryStage.setResizable(false);
// semaphore for synchronizing the closing
final Semaphore semaphore = new Semaphore(1);
// notify loop of window being closed
primaryStage.setOnHidden(evt -> semaphore.release());
final Scanner scanner = new Scanner(System.in);
System.out.println("Enter a number: ");
Runnable runnable = () -> {
while (true) {
// wait for window to be closed
try {
semaphore.acquire();
} catch (InterruptedException ex) {
return;
}
// read number
int xx = scanner.nextInt();
if (xx == 1) {
ArrayList<Boolean> bool = new ArrayList<>();
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
bool.add(true);
} else {
bool.add(false);
}
}
//Coordinate variables
int y = 50;
Node[] children = new Node[bool.size()];
//Rectangle loop
for (int i = 0; i < children.length; i++) {
Rectangle rectangle = new Rectangle(50, y, 150.0, 50.0);
rectangle.setFill(bool.get(i) ? RED : BLUE);
y += 50;
children[i] = rectangle;
}
// update gui
Platform.runLater(() -> {
root.getChildren().setAll(children);
primaryStage.show();
});
} else {
// shutdown javafx
Platform.exit();
break;
}
}
};
new Thread(runnable).start();
}