【发布时间】:2018-08-29 14:38:40
【问题描述】:
我一直在 YouTube、Stack-Overflow 和 fxexperience,甚至 oracle documentation 中搜索,但我仍然不明白。 没有类似的例子:(
问题是如何做一个堆栈和队列模拟器。
- 生成 10 个随机数。完成。
- 在表格中显示数字。完成。
- 使用 10 个随机数来模拟堆栈和队列。我现在不知道如何将服务与 TextField 通信。
- 暂停模拟。或停止。
-程序需要一个暂停方法。我不知道如何暂停前奏。也许用 wait() 和 notify()。我不知道。
我使用了 label.textProperty.bind(service.progressProperty())。这可行,但是当我尝试绑定变量时 updateProgress(i,n) 方法抛出异常。
也许我需要使用 2 个任务。
主类:
package simulation;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("/simulation/simulation.fxml"));
primaryStage.setTitle("JavaFX and concurrency, Stack and Queue");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
控制器类:
package simulation;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import java.net.URL;
import java.util.ResourceBundle;
public class SimulationCt implements Initializable {
@FXML private TableView table;
@FXML private TableColumn i_tc;
@FXML private TableColumn random_tc;
@FXML private TextField stack_start;
@FXML private TextField stack_1;
@FXML private TextField stack_2;
@FXML private TextField stack_3;
@FXML private TextField stack_4;
@FXML private TextField stack_5;
@FXML private TextField stack_final;
@FXML private TextField queue_start;
@FXML private TextField queue_1;
@FXML private TextField queue_2;
@FXML private TextField queue_3;
@FXML private TextField queue_4;
@FXML private TextField queue_5;
@FXML private TextField queue_final;
@FXML private Button new_b;
@FXML private Button play_pause_b;
@FXML private Button stop_b;
@FXML private ProgressBar progress_bar;
private ObservableList<RandomNumber> numberList = FXCollections.observableArrayList();
private CalculateService backProcess;
@FXML
private void createNew () {
disableNew(true);
generateRandom();
backProcess = new CalculateService();
progress_bar.progressProperty().bind(backProcess.progressProperty());
Platform.runLater(() -> {
backProcess.start();
});
}
@FXML
private void playPause () {
if(backProcess.getState().equals(Worker.State.RUNNING)) {
System.out.println("stoping...");
backProcess.cancel();
} else if (backProcess.getState().equals(Worker.State.CANCELLED)) {
System.out.println("restarting...");
backProcess.restart();
}
}
@FXML
private void stop () {
if(backProcess.getState().equals(Worker.State.RUNNING)) {
System.out.println("stoping...");
backProcess.cancel();
} else if (backProcess.getState().equals(Worker.State.CANCELLED)) {
System.out.println("already stoped...");
}
clearItems();
disableNew(false);
}
// cleans the list and the progress bar.
private void clearItems () {
progress_bar.progressProperty().unbind();
progress_bar.progressProperty().set(0.0);
numberList.clear();
}
private void disableNew (boolean b) {
new_b.setDisable(b);
play_pause_b.setDisable(!b);
stop_b.setDisable(!b);
}
// generates random numbers to fill the table, these numbers are the ones for the stack and the queue.
private void generateRandom () {
for (int i = 1; i < 11; i++) {
int rnd = (int)(Math.random() * (200 - 0 + 1)) + 0;
numberList.add(new RandomNumber(i, rnd ));
}
}
private void startTable () {
i_tc.setCellValueFactory( new PropertyValueFactory("i"));
random_tc.setCellValueFactory( new PropertyValueFactory("number"));
table.setItems(numberList);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
disableNew(false);
startTable();
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<AnchorPane id="AnchorPane" prefHeight="300.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="simulation.SimulationCt">
<children>
<TableView fx:id="table" layoutX="8.0" layoutY="10.0" prefHeight="282.0" prefWidth="162.0">
<columns>
<TableColumn fx:id="i_tc" prefWidth="28.0" text="i" />
<TableColumn fx:id="random_tc" prefWidth="122.0" text="Random Number" />
</columns>
</TableView>
<GridPane layoutX="303.0">
<columnConstraints>
<ColumnConstraints fillWidth="false" minWidth="10.0" prefWidth="50.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints fillWidth="false" halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0" prefWidth="50.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Stack" />
<VBox GridPane.rowIndex="1" GridPane.valignment="TOP">
<children>
<TextField fx:id="stack_start" prefHeight="25.0" prefWidth="25.0" />
<Label text="new" />
</children>
</VBox>
<VBox GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextField fx:id="stack_1" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="stack_2" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="stack_3" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="stack_4" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="stack_5" prefHeight="25.0" prefWidth="25.0" />
</children>
</VBox>
<VBox GridPane.columnIndex="2" GridPane.rowIndex="1" GridPane.valignment="TOP">
<children>
<TextField fx:id="stack_final" prefHeight="25.0" prefWidth="25.0" />
<Label text="last" />
</children>
</VBox>
</children>
</GridPane>
<GridPane layoutX="193.0" layoutY="155.0">
<columnConstraints>
<ColumnConstraints fillWidth="false" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints fillWidth="false" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Queue" GridPane.columnIndex="1" />
<VBox GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP">
<children>
<TextField fx:id="queue_start" prefHeight="25.0" prefWidth="25.0" />
<Label text="new" />
</children>
</VBox>
<HBox spacing="5.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextField fx:id="queue_1" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="queue_2" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="queue_3" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="queue_4" prefHeight="25.0" prefWidth="25.0" />
<TextField fx:id="queue_5" prefHeight="25.0" prefWidth="25.0" />
</children>
</HBox>
<VBox GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="TOP">
<children>
<TextField fx:id="queue_final" prefHeight="25.0" prefWidth="25.0" />
<Label text="last" />
</children>
</VBox>
</children>
</GridPane>
<Button fx:id="new_b" onAction="#createNew" layoutX="266.0" layoutY="243.0" mnemonicParsing="false" text="New" />
<Button fx:id="play_pause_b" onAction="#playPause" layoutX="326.0" layoutY="243.0" mnemonicParsing="false" text="Play / Pause" />
<Button fx:id="stop_b" onAction="#stop" layoutX="428.0" layoutY="243.0" mnemonicParsing="false" text="Stop" />
<ProgressBar fx:id="progress_bar" layoutX="266.0" layoutY="277.0" prefWidth="200.0" progress="0.0" />
</children>
</AnchorPane>
数据助手:
package simulation;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
public class RandomNumber {
private IntegerProperty i;
private IntegerProperty number;
public RandomNumber(int i, int number) {
this.i = new SimpleIntegerProperty(i);
this.number = new SimpleIntegerProperty(number);
}
public int getI() {
return i.get();
}
public IntegerProperty iProperty() {
return i;
}
public void setI(int i) {
this.i.set(i);
}
public int getNumber() {
return number.get();
}
public IntegerProperty numberProperty() {
return number;
}
public void setNumber(int number) {
this.number.set(number);
}
}
服务类:
package simulation;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class CalculateService extends Service {
int n = 20; // this does the trick to simulate the pause.
int j = 0; // even if the task is canceled the last value is saved here.
@Override
protected Task createTask() {
return new Task() {
@Override protected Void call() throws Exception {
int a;
int b;
int iterations;
for (iterations = j; iterations <= n; iterations++) {
j = iterations;
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
updateProgress(iterations, n);
System.out.println("number: " + j);
//Block the thread for a short time, but be sure
//to check the InterruptedException for cancellation
try {
Thread.sleep(100);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
}
}
return null;
}
};
}
}
【问题讨论】:
标签: java multithreading javafx