在 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 个问题:

  1. 您不得阻塞 JavaFX 应用程序线程。在该线程上执行的方法(如 Application.start)需要在短时间内 return 才能使 GUI 保持响应。如果您想继续使用 System.in(我不推荐),您需要为循环使用单独的线程。
  2. 关闭最后阶段将默认自动关闭JavaFX。这可以使用 Platform.setImplicitExit()
  3. 修复
@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();
}