JavaFX,primaryStage.show()之后的代码,怎么样?
JavaFX, code after primaryStage.show (), how?
我的目标是在 Stage + Scene 出现后每秒看到矩形的颜色变化。
我研究并尝试了几件事:
- primaryStage.show() 下的代码[看我的示例代码]
- primaryStage.setOnShown() 或 primaryStage.setOnShowing()
- 来自舞台的事件处理程序
- 来自场景的事件处理程序
- 带事件处理程序的按钮
一切都是徒劳。
在大多数情况下,舞台来了,然后程序在后台执行颜色更改(没有可视化),最后场景和最终结果一起出现。或者版本2:我什么也没看到,代码通过,最后立即得到最终结果。
这是我的代码:
package sample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
GridPane gridPane = new GridPane();
Rectangle[] recs = new Rectangle[10];
for (int i = 0; i < recs.length; i++) {
recs[i] = new Rectangle(30, 30, Color.GREEN);
recs[i].setStroke(Color.BLACK);
gridPane.add(recs[i], i, 0);
}
primaryStage.setTitle("Code after primaryStage.show()");
primaryStage.setScene(new Scene(gridPane, 400, 300));
primaryStage.show();
for (Rectangle rec : recs) {
Thread.sleep(1000);
rec.setFill(Color.ORANGE);
}
}
public static void main(String[] args) {
launch(args);
}
}
这里的问题是您的循环在主应用程序线程上 运行,因此它会锁定所有 GUI 更新,直到它完成。
改为在它自己的线程上执行循环并使用 Platform.runLater()
更新每个矩形:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
GridPane gridPane = new GridPane();
Rectangle[] recs = new Rectangle[10];
for (int i = 0; i < recs.length; i++) {
recs[i] = new Rectangle(30, 30, Color.GREEN);
recs[i].setStroke(Color.BLACK);
gridPane.add(recs[i], i, 0);
}
primaryStage.setTitle("Code after primaryStage.show()");
primaryStage.setScene(new Scene(gridPane, 400, 300));
primaryStage.show();
new Thread(() -> {
for (Rectangle rec :
recs) {
try {
Thread.sleep(1000);
Platform.runLater(() -> rec.setFill(Color.ORANGE));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
发生了什么事?
new Thread(() -> {
在您的应用程序后台打开一个新线程,以便 UI 保持响应。
然后我们可以在 try/catch
块中开始循环。
Platform.runLater(() -> rec.setFill(Color.ORANGE));
当使用后台线程时,重要的是要知道您不能直接对 UI 进行更改。此行告诉 JavaFX 在 JavaFX 应用程序线程上执行 rec.setFill()
语句。
.start();
您已经创建了新的 Thread
,这只是开始。
这是使用 TimeLine
的另一种方法。来自 here.
的代码
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
GridPane gridPane = new GridPane();
Rectangle[] recs = new Rectangle[10];
for (int i = 0; i < recs.length; i++) {
recs[i] = new Rectangle(30, 30, Color.GREEN);
recs[i].setStroke(Color.BLACK);
gridPane.add(recs[i], i, 0);
}
primaryStage.setTitle("Code after primaryStage.show()");
primaryStage.setScene(new Scene(gridPane, 400, 300));
primaryStage.show();
AtomicInteger counter = new AtomicInteger();
Timeline oneSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(1), (ActionEvent event) -> {
System.out.println("this is called every 1 second on UI thread");
recs[counter.getAndIncrement()].setFill(Color.ORANGE);
}));
oneSecondsWonder.setCycleCount(recs.length);
oneSecondsWonder.play();
}
public static void main(String[] args)
{
launch(args);
}
}
我的目标是在 Stage + Scene 出现后每秒看到矩形的颜色变化。
我研究并尝试了几件事:
- primaryStage.show() 下的代码[看我的示例代码]
- primaryStage.setOnShown() 或 primaryStage.setOnShowing()
- 来自舞台的事件处理程序
- 来自场景的事件处理程序
- 带事件处理程序的按钮
一切都是徒劳。 在大多数情况下,舞台来了,然后程序在后台执行颜色更改(没有可视化),最后场景和最终结果一起出现。或者版本2:我什么也没看到,代码通过,最后立即得到最终结果。
这是我的代码:
package sample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
GridPane gridPane = new GridPane();
Rectangle[] recs = new Rectangle[10];
for (int i = 0; i < recs.length; i++) {
recs[i] = new Rectangle(30, 30, Color.GREEN);
recs[i].setStroke(Color.BLACK);
gridPane.add(recs[i], i, 0);
}
primaryStage.setTitle("Code after primaryStage.show()");
primaryStage.setScene(new Scene(gridPane, 400, 300));
primaryStage.show();
for (Rectangle rec : recs) {
Thread.sleep(1000);
rec.setFill(Color.ORANGE);
}
}
public static void main(String[] args) {
launch(args);
}
}
这里的问题是您的循环在主应用程序线程上 运行,因此它会锁定所有 GUI 更新,直到它完成。
改为在它自己的线程上执行循环并使用 Platform.runLater()
更新每个矩形:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
GridPane gridPane = new GridPane();
Rectangle[] recs = new Rectangle[10];
for (int i = 0; i < recs.length; i++) {
recs[i] = new Rectangle(30, 30, Color.GREEN);
recs[i].setStroke(Color.BLACK);
gridPane.add(recs[i], i, 0);
}
primaryStage.setTitle("Code after primaryStage.show()");
primaryStage.setScene(new Scene(gridPane, 400, 300));
primaryStage.show();
new Thread(() -> {
for (Rectangle rec :
recs) {
try {
Thread.sleep(1000);
Platform.runLater(() -> rec.setFill(Color.ORANGE));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
发生了什么事?
new Thread(() -> {
在您的应用程序后台打开一个新线程,以便 UI 保持响应。
然后我们可以在 try/catch
块中开始循环。
Platform.runLater(() -> rec.setFill(Color.ORANGE));
当使用后台线程时,重要的是要知道您不能直接对 UI 进行更改。此行告诉 JavaFX 在 JavaFX 应用程序线程上执行 rec.setFill()
语句。
.start();
您已经创建了新的 Thread
,这只是开始。
这是使用 TimeLine
的另一种方法。来自 here.
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
GridPane gridPane = new GridPane();
Rectangle[] recs = new Rectangle[10];
for (int i = 0; i < recs.length; i++) {
recs[i] = new Rectangle(30, 30, Color.GREEN);
recs[i].setStroke(Color.BLACK);
gridPane.add(recs[i], i, 0);
}
primaryStage.setTitle("Code after primaryStage.show()");
primaryStage.setScene(new Scene(gridPane, 400, 300));
primaryStage.show();
AtomicInteger counter = new AtomicInteger();
Timeline oneSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(1), (ActionEvent event) -> {
System.out.println("this is called every 1 second on UI thread");
recs[counter.getAndIncrement()].setFill(Color.ORANGE);
}));
oneSecondsWonder.setCycleCount(recs.length);
oneSecondsWonder.play();
}
public static void main(String[] args)
{
launch(args);
}
}