问题
I have created a class called threads with a run() method that is supposed to print a rectangle. I cannot add this thread to the Pane because .add() does not accept threads. How can I successfully upload this thread onto my JavaFX screen? (The idea behind this is that each rectangle generated will be like a new monster, in which these monsters will attack an obstacle, lowering the health of it).
public class Threads implements Runnable {
@Override
public void run(){
Rectangle rect = new Rectangle((int) (Math.random() * 1000), (int) (Math.random() * 1000),100,100);
rect.setFill(Color.color(Math.random(), Math.random(), Math.random()));
}
}
public class SquareThreads extends Application {
@Override
public void start(Stage primaryStage) {
Pane root = new Pane();
Thread t1 = new Thread(new Threads ());
t1.start();
root.getChildren().add(t1);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
回答1:
Assuming you don't want to use JavaFx animation tools, like you did in this previous question, you can have a thread create rectangles in the background, and have your gui respond when new rectangles are created :
import java.util.concurrent.TimeUnit;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class SquareThreads extends Application {
@Override
public void start(Stage primaryStage) {
Pane pane = new Pane(); //container for shapes
MakeRectangles mr = new MakeRectangles (); //make new shapes on other thread
mr.getShapes().addListener((ListChangeListener<Shape>) change -> { //respond to shapes added
while (change.next()) {
//if items are removed
for (Shape s : change.getRemoved()) {
Platform.runLater(()-> pane.getChildren().remove(s));
}
//if items are added
for (Shape s : change.getAddedSubList()) {
Platform.runLater(()-> pane.getChildren().add(s));
}
}
});
Scene scene = new Scene(pane,600,600);
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.sizeToScene();
mr.start(); //start making new rectangles
}
public static void main(String[] args) {
launch(args);
}
}
class MakeRectangles implements Runnable {
//store the shapes created in an observable list
private final ObservableList<Shape> shapes;
private boolean cancel;
private final Thread t;
public MakeRectangles() {
shapes = FXCollections.observableArrayList();
t= new Thread(this);
}
@Override
public void run(){
cancel = false;
while (! cancel){
Rectangle rect = new Rectangle((int) (Math.random() * 600), (int) (Math.random() * 600),100,100);
rect.setFill(Color.color(Math.random(), Math.random(), Math.random()));
shapes.add(rect);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ex) { ex.printStackTrace(); }
}
}
ObservableList<Shape> getShapes(){
return shapes;
}
void start(){
stop(); //stop previous run if any
t.start();
}
void stop(){
cancel = true;
try {
t.join(); //wait for completion
} catch (InterruptedException ex) { ex.printStackTrace(); }
}
}
来源:https://stackoverflow.com/questions/54604430/how-to-multi-thread-in-javafx