I have a JavaFX application whose main job is to display different tables containing data loaded from CSV files. I can read CSV files into TableViews with no problems, and export them to CSVs as well. My problem is displaying the different TableViews.
When I load from a CSV into a TableView, I want to save that TableView for future processing. I also want to display a table showing the newly loaded data. My strategy is to have a global TableView, call it table, that is added to the main VBox, and update its contents to contain (and hence display) the elements of whichever TableView I just created by reading a file.
Is this a bad idea? It seems like a simple concept to me, but I can't find a way to easily "clone" the chosen TableView - i.e. transfer its contents to my displayed TableView called table.
My simple attempt at cloning TableViews is shown here. I also tried writing an extensive equateTable() method, which went nowhere.
//WHY DOESN'T THIS WORK?
table.setItems(reqTable.getItems());
Here's the rest of the code. Thanks to anyone who answers!
package FLOOR;
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Callback;
// --- Main Class
public class Main extends Application {
// --- All Tables
TableView<ObservableList<StringProperty>> reqTable = new TableView<>();
TableView<ObservableList<StringProperty>> tempTable = new TableView<>();
TableView<ObservableList<StringProperty>> ontTable = new TableView<>();
// --- Display Table
TableView<ObservableList<StringProperty>> table = new TableView<>();
// --- Main
public static void main(String[] args) {
launch(args);
}
// --- Start
#Override
public void start(Stage stage) {
// --- Stage & Scene
stage.setTitle("FLOOR");
Scene scene = new Scene(new VBox(), 900, 500);
MenuBar menuBar = new MenuBar();
// --- VBox
final VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.setPadding(new Insets(0, 10, 0, 10));
vbox.getChildren().addAll(table);
table.setVisible(false);
// --- Menus
// --- File Menu
// --- Import Submenu
Menu menuFile = new Menu("File");
Menu importMenu = new Menu("Import");
MenuItem reqOption = new MenuItem("Requirements");
MenuItem tempOption = new MenuItem("Templates");
MenuItem ontOption = new MenuItem("Ontologies");
importMenu.getItems().addAll(reqOption, tempOption, ontOption);
//Import Requirements
reqOption.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select Requirements CSV");
File file = fileChooser.showOpenDialog(stage);
if (file != null) {
populateTable(reqTable, file.getAbsolutePath());
}
getRequirementsPage();
}
});
//Import Templates
tempOption.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select Templates CSV");
File file = fileChooser.showOpenDialog(stage);
if (file != null) {
populateTable(tempTable, file.getAbsolutePath());
}
getTemplatesPage();
}
});
//Import Ontologies
ontOption.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select Ontology CSV");
File file = fileChooser.showOpenDialog(stage);
if (file != null) {
populateTable(ontTable, file.getAbsolutePath());
}
getOntologiesPage();
}
});
//Export
MenuItem export = new MenuItem("Export");
export.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save Requirements CSV");
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
exportTable(reqTable, file.getAbsolutePath());
}
}
});
//Exit
MenuItem exit = new MenuItem("Exit");
exit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
System.exit(0);
}
});
menuFile.getItems().addAll(importMenu, export, new SeparatorMenuItem(), exit);
// --- Menu Bar
menuBar.getMenus().addAll(menuFile);
// --- Show FLOOR
((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);
stage.setScene(scene);
stage.show();
}
// --- Methods
// Table Getters
private void getRequirementsPage() {
table.getItems().clear();
//WHY DOESN'T THIS WORK?
table.setItems(reqTable.getItems());
table.setVisible(true);
}
private void getTemplatesPage() {
table.getItems().clear();
table.setItems(tempTable.getItems());
table.setVisible(true);
}
private void getOntologiesPage() {
table.getItems().clear();
table.setItems(ontTable.getItems());
table.setVisible(true);
}
//populateTable
private void populateTable(
final TableView<ObservableList<StringProperty>> table,
final String filename) {
table.getItems().clear();
table.getColumns().clear();
table.setPlaceholder(new Label("Loading..."));
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
CSVReader reader = new CSVReader(new FileReader(filename));
String [] nextLine;
int count = 1;
while ((nextLine = reader.readNext()) != null) {
if (count == 1) {
final String[] headers = nextLine;
Platform.runLater(new Runnable() {
#Override
public void run() {
for (int column = 0; column < headers.length; column++) {
table.getColumns().add(
createColumn(column, headers[column]));
}
}
});
} else {
final String[] dataValues = nextLine;
Platform.runLater(new Runnable() {
#Override
public void run() {
// Add additional columns if necessary:
for (int columnIndex = table.getColumns().size(); columnIndex < dataValues.length; columnIndex++) {
table.getColumns().add(createColumn(columnIndex, ""));
}
// Add data to table:
ObservableList<StringProperty> data = FXCollections
.observableArrayList();
for (String value : dataValues) {
data.add(new SimpleStringProperty(value));
}
table.getItems().add(data);
}
});
}
count++;
}
reader.close();
return null;
}
};
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
//exportTable
private void exportTable(
final TableView<ObservableList<StringProperty>> table,
final String filename) {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
CSVWriter writer = null;
try {
writer = new CSVWriter(new FileWriter(filename), ',');
} catch (IOException e) {
e.printStackTrace();
}
int numRows = table.getItems().size();
int numCols = table.getColumns().size();
String[] dataWrite = new String[numCols];
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
dataWrite[j] = table.getItems().get(i).get(j).getValue();
}
writer.writeNext(dataWrite);
}
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
};
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
//createColumn
private TableColumn<ObservableList<StringProperty>, String> createColumn(
final int columnIndex, String columnTitle) {
TableColumn<ObservableList<StringProperty>, String> column = new TableColumn<>();
String title;
if (columnTitle == null || columnTitle.trim().length() == 0) {
title = "Column " + (columnIndex + 1);
} else {
title = columnTitle;
}
column.setText(title);
column
.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList<StringProperty>, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(
CellDataFeatures<ObservableList<StringProperty>, String> cellDataFeatures) {
ObservableList<StringProperty> values = cellDataFeatures.getValue();
if (columnIndex >= values.size()) {
return new SimpleStringProperty("");
} else {
return cellDataFeatures.getValue().get(columnIndex);
}
}
});
return column;
}
}
Related
I'm trying to do the following in JavaFX:
Have a TableView with multiple rows.
Each row contains columns with text and one Progress/Status column.
When a specific Button is pressed, for each row of the TableView some task should be performed, one row after the other. (e.g. check some data, ...)
While this task is performed, a indeterminate ProgressIndicator shall be shown in the Status column, until the task for this row is finished, then the indicator shows as done.
When all tasks for each row are done, the button can be pressed again to reset the status and execute the tasks again.
I had found some help in this related Stackoverflow post and also here and tried to tweak this as needed but got stuck on some issues:
Currently, each ProgressIndicator for each row is displayed immediately (as indeterminate) when I run the program. How can I only activate them / make them visible for each row one after another once the button is pressed?
Pressing the button again once the fake tasks are done does not restart it. How would I have to modify / rebuild the program to make resets possible?
Does the overall approach make sense?
My current runnable code:
import java.util.Random;
import java.util.concurrent.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ProgressIndicatorTableCellTest extends Application {
public void start(Stage primaryStage) {
TableView<TestTask> table = new TableView<>();
Random rng = new Random();
for (int i = 0; i < 3; i++) {
table.getItems().add(new TestTask(rng.nextInt(3000) + 2000, "Test"));
}
TableColumn<TestTask, String> nameCol = new TableColumn("Name");
nameCol.setCellValueFactory(new PropertyValueFactory<TestTask, String>("name"));
nameCol.setPrefWidth(75);
TableColumn<TestTask, Double> progressCol = new TableColumn("Progress");
progressCol.setCellValueFactory(new PropertyValueFactory<TestTask, Double>("progress"));
progressCol.setCellFactory(ProgressIndicatorTableCell.<TestTask>forTableColumn());
table.getColumns().addAll(nameCol, progressCol);
BorderPane root = new BorderPane();
root.setCenter(table);
Button btn = new Button("Start");
btn.setOnAction(actionEvent -> {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (TestTask task : table.getItems()) {
executor.submit(task);
}
});
root.setBottom(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class TestTask extends Task<Void> {
private final int waitTime; // milliseconds
final ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
public static final int NUM_ITERATIONS = 100;
public TestTask(int waitTime, String name) {
this.waitTime = waitTime;
this.name.set(name);
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
#Override
protected Void call() throws Exception {
this.updateProgress(ProgressIndicator.INDETERMINATE_PROGRESS, 1);
Thread.sleep(waitTime);
this.updateProgress(1, 1);
return null;
}
}
}
class ProgressIndicatorTableCell<S> extends TableCell<S, Double> {
public static <S> Callback<TableColumn<S, Double>, TableCell<S, Double>> forTableColumn() {
return new Callback<TableColumn<S, Double>, TableCell<S, Double>>() {
#Override
public TableCell<S, Double> call(TableColumn<S, Double> param) {
return new ProgressIndicatorTableCell<>();
}
};
}
private final ProgressIndicator progressIndicator;
private ObservableValue observable;
public ProgressIndicatorTableCell() {
this.progressIndicator = new ProgressIndicator();
setGraphic(progressIndicator);
}
#Override
public void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
progressIndicator.progressProperty().unbind();
observable = getTableColumn().getCellObservableValue(getIndex());
if (observable != null) {
progressIndicator.progressProperty().bind(observable);
} else {
progressIndicator.setProgress(item);
}
setGraphic(progressIndicator);
}
}
}
And the current output:
Here is a version that implements your first question. With this requirement, the cell is only a function of the task's state. If it's RUNNING, display an indeterminate progress indicator; if it's SUCCEEDED display a progress indicator with value 1; otherwise, display nothing.
Note the original question is very old and uses a lot of outdated code styles. I've updated accordingly.
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ProgressIndicatorTableCellTest extends Application {
public void start(Stage primaryStage) {
TableView<TestTask> table = new TableView<>();
Random rng = new Random();
for (int i = 0; i < 3; i++) {
table.getItems().add(new TestTask(rng.nextInt(3000) + 2000, "Test"));
}
TableColumn<TestTask, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(data -> data.getValue().nameProperty());
nameCol.setPrefWidth(75);
TableColumn<TestTask, Worker.State> progressCol = new TableColumn<>("Progress");
progressCol.setCellValueFactory(data -> data.getValue().stateProperty());
progressCol.setCellFactory(col -> new ProgressIndicatorTableCell<>());
table.getColumns().addAll(nameCol, progressCol);
BorderPane root = new BorderPane();
root.setCenter(table);
Button btn = new Button("Start");
btn.setOnAction(actionEvent -> {
ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
});
for (TestTask task : table.getItems()) {
executor.submit(task);
}
});
root.setBottom(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class TestTask extends Task<Void> {
private final int waitTime; // milliseconds
final ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
public static final int NUM_ITERATIONS = 100;
public TestTask(int waitTime, String name) {
this.waitTime = waitTime;
this.name.set(name);
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
#Override
protected Void call() throws Exception {
this.updateProgress(ProgressIndicator.INDETERMINATE_PROGRESS, 1);
Thread.sleep(waitTime);
this.updateProgress(1, 1);
return null;
}
}
}
class ProgressIndicatorTableCell<S> extends TableCell<S, Worker.State> {
private final ProgressIndicator progressIndicator = new ProgressIndicator();
#Override
protected void updateItem(Worker.State state, boolean empty) {
super.updateItem(state, empty);
if (state == Worker.State.SUCCEEDED) {
progressIndicator.setProgress(1);
setGraphic(progressIndicator);
} else if (state == Worker.State.RUNNING) {
progressIndicator.setProgress(-1);
setGraphic(progressIndicator);
} else {
setGraphic(null);
}
}
}
To allow for "restarting", you should use a Service instead of just a Task. This version will allow for a restart if the button is pressed multiple times, returning everything to the initial state before proceeding.
This version also factors the processing work out of the model class, which is desirable for properly assigning responsibilities to classes:
Item.java:
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleObjectProperty;
public class Item {
public enum State {WAITING, PROCESSING, READY}
final ReadOnlyStringWrapper name = new ReadOnlyStringWrapper();
private final ObjectProperty<State> state = new SimpleObjectProperty<>(State.WAITING);
public Item(String name) {
this.name.set(name);
}
public ReadOnlyStringProperty nameProperty() {
return name.getReadOnlyProperty();
}
public State getState() {
return state.get();
}
public ObjectProperty<State> stateProperty() {
return state;
}
public void setState(State state) {
this.state.set(state);
}
}
ProcessManager.java:
import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import java.util.List;
import java.util.Random;
public class ProcessManager {
private final List<Item> items;
private Random rng = new Random();
private Service<Void> service = new Service<>() {
#Override
protected Task<Void> createTask() {
return new Task<>() {
#Override
protected Void call() throws Exception {
for (Item task: items) {
try {
Platform.runLater(() -> task.setState(Item.State.PROCESSING));
Thread.sleep(2000 + rng.nextInt(3000));
Platform.runLater(() -> task.setState(Item.State.READY));
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
}
if (isCancelled()) {
Platform.runLater(() -> task.setState(Item.State.WAITING));
break;
}
}
return null;
}
};
}
};
public ProcessManager(List<Item> items) {
this.items = items ;
service.setOnCancelled(e -> items.forEach(task -> task.setState(Item.State.WAITING)));
}
public void process() {
service.restart();
}
}
and the application:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ProgressIndicatorTableCellTest extends Application {
public void start(Stage primaryStage) {
ObservableList<Item> tasks = FXCollections.observableArrayList();
ProcessManager processManager = new ProcessManager(tasks);
TableView<Item> table = new TableView<>();
for (int i = 0; i < 3; i++) {
Item task = new Item("Item " + (i + 1));
tasks.add(task);
}
table.setItems(tasks);
TableColumn<Item, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(data -> data.getValue().nameProperty());
nameCol.setPrefWidth(75);
TableColumn<Item, Item.State> progressCol = new TableColumn<>("Progress");
progressCol.setCellValueFactory(data -> data.getValue().stateProperty());
progressCol.setCellFactory(col -> new TableCell<>() {
private final ProgressIndicator indicator = new ProgressIndicator();
#Override
protected void updateItem(Item.State state, boolean empty) {
super.updateItem(state, empty);
if (state == Item.State.PROCESSING) {
indicator.setProgress(-1);
setGraphic(indicator);
} else if (state == Item.State.READY) {
indicator.setProgress(1);
setGraphic(indicator);
} else {
setGraphic(null);
}
}
});
table.getColumns().addAll(nameCol, progressCol);
BorderPane root = new BorderPane();
root.setCenter(table);
Button btn = new Button("Start");
btn.setOnAction(actionEvent -> processManager.process());
root.setBottom(btn);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I am tasked with creating a DVD Collection application that displays Three columns and five row of stuff. I have written the code for this to work but keep on getting compilation errors( CANNOT FIND SYMBOL ==> class DVDColletionApp ) that I am having a hard time debugging.
Below is the code in question. Assistance would be greatly appreciated.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
public class DVDCollectionApp extends Application {
private DVDCollection model;
private ListView<String> tList;
private ListView<Integer> yList, lList;
public DVDCollectionApp() {
model = DVDCollection.example1();
}
public void start(Stage primaryStage) {
BorderPane borderPane = new BorderPane();
// Create the labels
HBox labelPane = new HBox();
labelPane.setPadding(new Insets(0,0,0,10));
labelPane.setSpacing(10);
Label label1 = new Label("Title");
label1.setMinSize(300,30);
label1.setPrefSize(2000,30);
Label label2 = new Label("Year");
label2.setMinSize(60,30);
label2.setPrefSize(60,30);
Label label3 = new Label("Length");
label3.setMinSize(60,30);
label3.setPrefSize(60,30);
labelPane.getChildren().addAll(label1, label2, label3);
borderPane.setTop(labelPane);
// Create the lists
GridPane listPane = new GridPane();
listPane.setPadding(new Insets(10));
listPane.setHgap(10);
tList = new ListView<String>();
listPane.add(tList, 0, 0);
tList.setMinSize(300,60);
tList.setPrefSize(2000,2000);
yList = new ListView<Integer>();
listPane.add(yList, 1, 0);
yList.setMinSize(60,60);
yList.setPrefSize(60,500);
lList = new ListView<Integer>();
listPane.add(lList, 2, 0);
lList.setMinSize(60,60);
lList.setPrefSize(60,500);
borderPane.setCenter(listPane);
// Create the button pane
HBox buttonPane = new HBox();
buttonPane.setPadding(new Insets(10));
buttonPane.setSpacing(10);
Button addButton = new Button("Add");
addButton.setStyle("-fx-font: 12 arial; -fx-base: rgb(0,100,0); -fx-text-fill: rgb(255,255,255);");
addButton.setPrefSize(90,30);
Button deleteButton = new Button("Delete");
deleteButton.setStyle("-fx-font: 12 arial; -fx-base: rgb(200,0,0); -fx-text-fill: rgb(255,255,255);");
deleteButton.setPrefSize(90,30);
Button statsButton = new Button("Stats");
statsButton.setStyle("-fx-font: 12 arial;");
statsButton.setPrefSize(90,30);
buttonPane.getChildren().addAll(addButton, deleteButton, statsButton);
borderPane.setBottom(buttonPane);
addButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent actionEvent) {
String title = javax.swing.JOptionPane.showInputDialog("Please enter the DVD Title: ");
String year = javax.swing.JOptionPane.showInputDialog("Please enter the DVD Year: ");
String length = javax.swing.JOptionPane.showInputDialog("Please enter the DVD Duration: ");
if ((title != null) && (year != null) && (length != null) && (title.length() > 0) && (year.length() > 0) && (length.length() > 0)) {
DVD d = new DVD(title, Integer.parseInt(year), Integer.parseInt(length));
model.add(d);
update(model, -1);
}
}
});
deleteButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent actionEvent) {
if (tList.getSelectionModel().getSelectedItem() != null) {
model.remove(tList.getSelectionModel().getSelectedItem());
update(model, -1);
}
}
});
tList.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
model.setSelectedDVD(tList.getSelectionModel().getSelectedIndex());
update(model, tList.getSelectionModel().getSelectedIndex());
}
});
yList.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
model.setSelectedDVD(yList.getSelectionModel().getSelectedIndex());
update(model, yList.getSelectionModel().getSelectedIndex());
}
});
lList.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
model.setSelectedDVD(lList.getSelectionModel().getSelectedIndex());
update(model, lList.getSelectionModel().getSelectedIndex());
}
});
// Populate the lists
DVD[] theList = model.getDVDList();
String[] titles = new String[theList.length];
Integer[] years = new Integer[theList.length];
Integer[] lengths = new Integer[theList.length];
for (int i=0; i<theList.length; i++) {
titles[i] = theList[i].getTitle();
years[i] = theList[i].getYear();
lengths[i] = theList[i].getDuration();
}
tList.setItems(FXCollections.observableArrayList(titles));
yList.setItems(FXCollections.observableArrayList(years));
lList.setItems(FXCollections.observableArrayList(lengths));
primaryStage.setTitle("My DVD Collection");
primaryStage.setScene(new Scene(borderPane, 600, 300));
primaryStage.show();
}
// Update the view to reflect the model
public void update(DVDCollection model, int selectedDVD) {
DVD[] theList = model.getDVDList();
String[] titles = new String[theList.length];
Integer[] years = new Integer[theList.length];
Integer[] lengths = new Integer[theList.length];
for (int i=0; i<theList.length; i++) {
titles[i] = theList[i].getTitle();
years[i] = theList[i].getYear();
lengths[i] = theList[i].getDuration();
}
tList.setItems(FXCollections.observableArrayList(titles));
yList.setItems(FXCollections.observableArrayList(years));
lList.setItems(FXCollections.observableArrayList(lengths));
tList.getSelectionModel().select(selectedDVD);
yList.getSelectionModel().select(selectedDVD);
lList.getSelectionModel().select(selectedDVD);
}
public static void main(String[] args) {
launch(args);
}
}
Have you checked that java files are being compiled correctly?
The class DVDCollection doesn't seem to be imported, the DVDCollectionApp class must be in a .java of the same name and if you're using an IDE be sure to do a clean&build.
I want a tableview to take in values when end user copies data from excel and pastes it on the tableview..
I want to know the best approach so as of now there isn't any code to post... I want to use Clipboard class and manually add content from the clipboard to the table...
Is that the right approach?
If not. How to do it?
Are there any methods or classes which already implement this
functionality..?
You can do it like this. But you need to adapt the code to match your requirements (e. g. numberformatting, etc).
TableCopyPasteCellsDemo.java
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class TableCopyPasteCellsDemo extends Application {
private final ObservableList<Person> data = FXCollections.observableArrayList(new Person("Jacob", "Smith", 18), new Person("Isabella", "Johnson", 19), new Person("Ethan", "Williams", 20), new Person("Michael", "Brown", 21));
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
stage.setWidth(500);
stage.setHeight(550);
// create table columns
TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
TableColumn<Person, Integer> ageCol = new TableColumn<Person, Integer>("Age");
ageCol.setMinWidth(60);
ageCol.setCellValueFactory(new PropertyValueFactory<Person, Integer>("age"));
TableView<Person> table = new TableView<>();
table.setPlaceholder(new Text("No content in table"));
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, ageCol);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 10, 10, 10));
BorderPane borderPane = new BorderPane();
borderPane.setCenter(table);
vbox.getChildren().addAll(borderPane);
vbox.getChildren().add( new Label( "Select cells and press CTRL+C. Paste the data into Excel or Notepad"));
Scene scene = new Scene(vbox);
stage.setScene(scene);
stage.show();
// enable multi-selection
table.getSelectionModel().setCellSelectionEnabled(true);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// enable copy/paste
TableUtils.installCopyPasteHandler(table);
}
public static class Person {
private final StringProperty firstName;
private final StringProperty lastName;
private final IntegerProperty age;
private Person(String fName, String lName, Integer age) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.age = new SimpleIntegerProperty(age);
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final java.lang.String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final java.lang.String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final java.lang.String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final java.lang.String lastName) {
this.lastNameProperty().set(lastName);
}
public final IntegerProperty ageProperty() {
return this.age;
}
public final int getAge() {
return this.ageProperty().get();
}
public final void setAge(final int age) {
this.ageProperty().set(age);
}
}
}
TableUtils.java
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.StringTokenizer;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
public class TableUtils {
private static NumberFormat numberFormatter = NumberFormat.getNumberInstance();
/**
* Install the keyboard handler:
* + CTRL + C = copy to clipboard
* + CTRL + V = paste to clipboard
* #param table
*/
public static void installCopyPasteHandler(TableView<?> table) {
// install copy/paste keyboard handler
table.setOnKeyPressed(new TableKeyEventHandler());
}
/**
* Copy/Paste keyboard event handler.
* The handler uses the keyEvent's source for the clipboard data. The source must be of type TableView.
*/
public static class TableKeyEventHandler implements EventHandler<KeyEvent> {
KeyCodeCombination copyKeyCodeCompination = new KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_ANY);
KeyCodeCombination pasteKeyCodeCompination = new KeyCodeCombination(KeyCode.V, KeyCombination.CONTROL_ANY);
public void handle(final KeyEvent keyEvent) {
if (copyKeyCodeCompination.match(keyEvent)) {
if( keyEvent.getSource() instanceof TableView) {
// copy to clipboard
copySelectionToClipboard( (TableView<?>) keyEvent.getSource());
// event is handled, consume it
keyEvent.consume();
}
}
else if (pasteKeyCodeCompination.match(keyEvent)) {
if( keyEvent.getSource() instanceof TableView) {
// copy to clipboard
pasteFromClipboard( (TableView<?>) keyEvent.getSource());
// event is handled, consume it
keyEvent.consume();
}
}
}
}
/**
* Get table selection and copy it to the clipboard.
* #param table
*/
public static void copySelectionToClipboard(TableView<?> table) {
StringBuilder clipboardString = new StringBuilder();
ObservableList<TablePosition> positionList = table.getSelectionModel().getSelectedCells();
int prevRow = -1;
for (TablePosition position : positionList) {
int row = position.getRow();
int col = position.getColumn();
// determine whether we advance in a row (tab) or a column
// (newline).
if (prevRow == row) {
clipboardString.append('\t');
} else if (prevRow != -1) {
clipboardString.append('\n');
}
// create string from cell
String text = "";
Object observableValue = (Object) table.getColumns().get(col).getCellObservableValue( row);
// null-check: provide empty string for nulls
if (observableValue == null) {
text = "";
}
else if( observableValue instanceof DoubleProperty) { // TODO: handle boolean etc
text = numberFormatter.format( ((DoubleProperty) observableValue).get());
}
else if( observableValue instanceof IntegerProperty) {
text = numberFormatter.format( ((IntegerProperty) observableValue).get());
}
else if( observableValue instanceof StringProperty) {
text = ((StringProperty) observableValue).get();
}
else {
System.out.println("Unsupported observable value: " + observableValue);
}
// add new item to clipboard
clipboardString.append(text);
// remember previous
prevRow = row;
}
// create clipboard content
final ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString(clipboardString.toString());
// set clipboard content
Clipboard.getSystemClipboard().setContent(clipboardContent);
}
public static void pasteFromClipboard( TableView<?> table) {
// abort if there's not cell selected to start with
if( table.getSelectionModel().getSelectedCells().size() == 0) {
return;
}
// get the cell position to start with
TablePosition pasteCellPosition = table.getSelectionModel().getSelectedCells().get(0);
System.out.println("Pasting into cell " + pasteCellPosition);
String pasteString = Clipboard.getSystemClipboard().getString();
System.out.println(pasteString);
int rowClipboard = -1;
StringTokenizer rowTokenizer = new StringTokenizer( pasteString, "\n");
while( rowTokenizer.hasMoreTokens()) {
rowClipboard++;
String rowString = rowTokenizer.nextToken();
StringTokenizer columnTokenizer = new StringTokenizer( rowString, "\t");
int colClipboard = -1;
while( columnTokenizer.hasMoreTokens()) {
colClipboard++;
// get next cell data from clipboard
String clipboardCellContent = columnTokenizer.nextToken();
// calculate the position in the table cell
int rowTable = pasteCellPosition.getRow() + rowClipboard;
int colTable = pasteCellPosition.getColumn() + colClipboard;
// skip if we reached the end of the table
if( rowTable >= table.getItems().size()) {
continue;
}
if( colTable >= table.getColumns().size()) {
continue;
}
// System.out.println( rowClipboard + "/" + colClipboard + ": " + cell);
// get cell
TableColumn tableColumn = table.getColumns().get(colTable);
ObservableValue observableValue = tableColumn.getCellObservableValue(rowTable);
System.out.println( rowTable + "/" + colTable + ": " +observableValue);
// TODO: handle boolean, etc
if( observableValue instanceof DoubleProperty) {
try {
double value = numberFormatter.parse(clipboardCellContent).doubleValue();
((DoubleProperty) observableValue).set(value);
} catch (ParseException e) {
e.printStackTrace();
}
}
else if( observableValue instanceof IntegerProperty) {
try {
int value = NumberFormat.getInstance().parse(clipboardCellContent).intValue();
((IntegerProperty) observableValue).set(value);
} catch (ParseException e) {
e.printStackTrace();
}
}
else if( observableValue instanceof StringProperty) {
((StringProperty) observableValue).set(clipboardCellContent);
} else {
System.out.println("Unsupported observable value: " + observableValue);
}
System.out.println(rowTable + "/" + colTable);
}
}
}
}
Why these statements does not work?
if (iv_ship.intersects(iv_plane.getBoundsInLocal())) System.out.println("xxxxxxxxx");
if (iv_plane.intersects(iv_ship.getBoundsInLocal())) System.out.println("zzzz");
if (iv_plane.getBoundsInLocal().intersects(iv_ship.getBoundsInLocal())) System.out.println("dupa");
I am pretty sure these two objects intersect. Maybe it is fault of TranslateTransition?
But i was also trying to intersect Rectangles in coast, which are not TT.
Best regards.
Here is all the code:
package riverpuff.v3;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* #author Marek
*/
public class RiverPuffV3 extends Application {
public String name = "";
public Rectangle shot = new Rectangle();
#Override
public void start(Stage primaryStage) {
createMenu(primaryStage);
primaryStage.show();
primaryStage.setResizable(false);
primaryStage.getIcons().
add(new Image(getClass().getResourceAsStream("Icon.png")));
}
private void createMenu(Stage primaryStage) {
primaryStage.setScene(null);
GridPane pane_menu = new GridPane();
Button button_name = new Button("Name");
button_name.setMaxHeight(Double.MAX_VALUE);
button_name.setMaxWidth(Double.MAX_VALUE);
button_name.setOnAction(e -> {
createName(primaryStage);
/*try{
OutputStreamWriter writer = new OutputStreamWriter( new FileOutputStream("log.txt", true), "UTF-8");
BufferedWriter fbw = new BufferedWriter(writer);
fbw.newLine();
fbw.write("append txt...");
fbw.newLine();
fbw.close();
}
catch (Exception v) {
System.out.println("Error: " + v.getMessage());
}*/
});
Button button_start = new Button("Start");
button_start.setMaxHeight(Double.MAX_VALUE);
button_start.setMaxWidth(Double.MAX_VALUE);
button_start.setOnAction(e -> {
drawGame(primaryStage);
});
pane_menu.setHgap(10);
pane_menu.setVgap(10);
pane_menu.add(button_name,0,10,10,10);
pane_menu.add(button_start,15,10,10,10);
//reading name from a file
try {
String read_file = null;
BufferedReader in = new BufferedReader(new FileReader("log.txt"));
read_file = in.readLine();
Text text_name = new Text("Hello " + read_file);
pane_menu.add(text_name,5,5,10,5);
} catch (FileNotFoundException e) {
System.out.println("File not found!");
//throw new RuntimeException("File not found");
} catch (IOException e) {
System.out.println("IO Error occured");
//throw new RuntimeException("IO Error occured");
}
Scene scene_menu = new Scene(pane_menu, 300, 500);
primaryStage.setTitle("River Puff");
primaryStage.setScene(scene_menu);
}
//save name to a file
private void createName (Stage primaryStage) {
primaryStage.setScene(null);
GridPane pane_name = new GridPane();
TextField tf_name = new TextField();
tf_name.setMaxHeight(50);
tf_name.setMaxWidth(240);
tf_name.setAlignment(Pos.CENTER);
tf_name.setFont(Font.font("Verdana",25));
tf_name.setOnKeyPressed(ke -> {
if (ke.getCode() == KeyCode.ENTER) {
name = tf_name.getText();
if (!name.isEmpty()){
MyFile myFile = new MyFile();
myFile.writeTextFile("log.txt", name);
}
createMenu(primaryStage);
}
});
Button button_ok = new Button("OK");
button_ok.setMaxHeight(30);
button_ok.setMaxWidth(80);
button_ok.setOnAction(e -> {
name = tf_name.getText();
if (!name.isEmpty()){
MyFile myFile = new MyFile();
myFile.writeTextFile("log.txt", name);
}
createMenu(primaryStage);
});
Text text_name = new Text("What is your name?");
text_name.setFont(Font.font("Verdana",15));
pane_name.setHgap(10);
pane_name.setVgap(10);
pane_name.add(text_name,8,9,5,5);
pane_name.add(button_ok,11,22,8,3);
pane_name.add(tf_name,3,15,24,5);
Scene scene_name = new Scene(pane_name, 300, 500);
primaryStage.setTitle("River Puff - Name");
primaryStage.setScene(scene_name);
}
private void drawGame (Stage primaryStage) {
primaryStage.setScene(null);
final int H = 700;
final int W = 1000;
Group root = new Group();
Scene scene_game = new Scene(root, W, H, Color.LIGHTBLUE);
Button button_menu = new Button("Menu");
button_menu.setOnAction(e ->{
createMenu(primaryStage);
});
Image ship = new Image((getClass().getResourceAsStream("ship.png"))); //loading images
Image plane = new Image((getClass().getResourceAsStream("Icon.png")));
/**********************************************************************/
Rectangle[] coastL = {
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle()
};
Rectangle[] coastR = {
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle()
};
for (int i=0; i<8; i++) {
coastL[i].setFill(Color.FORESTGREEN);
coastL[i].setHeight(100);
coastR[i].setFill(Color.FORESTGREEN);
coastR[i].setHeight(100);
}
AnimationTimer timer = new AnimationTimer() {
int[] j = {0,0,0,0,0,0,0,0};
#Override
public void handle(long now) {
for (int i=0; i<8; i++) if (j[i]==(i*100+800)) j[i]=i*100;
for (int i=1;i<9;i++) { //creating coast
coastL[i-1].setX(0);
coastL[i-1].setY(j[i-1]-(i*100));
coastL[i-1].setWidth(250+i*(i%3));
coastR[i-1].setX(W-(250+i*(i%4)));
coastR[i-1].setY(j[i-1]-(i*100));
coastR[i-1].setWidth(250+i*(i%4));
}
for (int i=0;i<8;i++) j[i]++;
}
};
timer.start();
ImageView iv_ship = new ImageView();
iv_ship.setImage(ship);
iv_ship.setFitWidth(150);
iv_ship.setFitHeight(45);
iv_ship.setX(300);
iv_ship.setY(0);
TranslateTransition tt_shipX =
new TranslateTransition(Duration.millis(2000), iv_ship); //moving enemies
tt_shipX.setAutoReverse(true);
tt_shipX.setCycleCount(Timeline.INDEFINITE);
tt_shipX.setByX(200f);
tt_shipX.play();
TranslateTransition tt_shipY =
new TranslateTransition(Duration.millis(13000), iv_ship);
tt_shipY.setAutoReverse(false);
tt_shipY.setCycleCount(Timeline.INDEFINITE);
tt_shipY.setByY(800);
tt_shipY.play();
ImageView iv_plane = new ImageView();
iv_plane.setImage(plane);
iv_plane.setFitWidth(50);
iv_plane.setFitHeight(50);
iv_plane.setX(475);
iv_plane.setY(600);
TranslateTransition tt_plane =
new TranslateTransition(Duration.millis(1), iv_plane);
TranslateTransition tt_shot =
new TranslateTransition(Duration.millis(4000), shot);
tt_shot.setAutoReverse(false);
tt_shot.setCycleCount(1);
TranslateTransition tt_shotB =
new TranslateTransition(Duration.millis(0.5f), shot);
tt_shotB.setAutoReverse(false);
tt_shotB.setCycleCount(1);
root.setOnKeyPressed((KeyEvent ke) -> { //steering a plane }
if (ke.getCode() == KeyCode.LEFT &&
tt_plane.getNode().getTranslateX() > -475) {
tt_plane.setByX(-5f);
tt_plane.play();
System.out.println(tt_plane.getNode().getTranslateX());
}
else if (ke.getCode() == KeyCode.RIGHT &&
tt_plane.getNode().getTranslateX() < 475) {
tt_plane.setByX(5f);
tt_plane.play();
System.out.println(tt_plane.getNode().getTranslateX());
}
else if (ke.getCode() == KeyCode.A) {
shot.setFill(Color.BLACK);
shot.setX(tt_plane.getNode().getTranslateX()+495);
shot.setY(580);
shot.setWidth(10);
shot.setHeight(20);
tt_shot.setByY(-600);
tt_shot.play();
tt_shot.setOnFinished((ActionEvent arg0) -> {
shot.setDisable(true);
tt_shotB.setByY(600);
tt_shotB.play();
});
}
});
if (iv_ship.intersects(iv_plane.getBoundsInLocal())) System.out.println("xxxxxxxxx");
if (iv_plane.intersects(iv_ship.getBoundsInLocal())) System.out.println("zzzz");
if (iv_plane.getBoundsInLocal().intersects(iv_ship.getBoundsInLocal())) System.out.println("dupa");
root.getChildren().add(button_menu);
for (int i=0; i<8; i++) {
root.getChildren().add(coastL[i]);
root.getChildren().add(coastR[i]);
}
root.getChildren().add(iv_plane);
root.getChildren().add(iv_ship);
root.getChildren().add(shot);
primaryStage.setScene(scene_game);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
First of all, you need to take into account that the nodes can be transformed (with translations), so instead of getBoundsInLocal() you need getBoundsInParent().
According to javadocs:
getBoundsInParent() gets the value of the property boundsInParent. The rectangular bounds of this Node which include its transforms. boundsInParent is calculated by taking the local bounds (defined by boundsInLocal) and applying the transform created.
This will work, at any given position of both nodes:
if(iv_plane.getBoundsInParent().intersects(iv_ship.getBoundsInParent())){
System.out.println("Intersection detected");
}
The next problem you have to solve is when do you check a possible intersection. Based on your code, you checked only once, when the nodes where not even added to the root/scene/stage. That couldn't work.
For this to work, you have to check everytime one of them is moved, using some listeners to changes in the translateXProperty() and translateYProperty(), something like this:
private final ChangeListener<Number> checkIntersection = (ob,n,n1)->{
if (iv_plane.getBoundsInParent().intersects(iv_ship.getBoundsInParent())){
System.out.println("Intersection detected");
}
};
private ImageView iv_ship, iv_plane;
private void drawGame (Stage primaryStage) {
iv_ship = new ImageView();
iv_plane = new ImageView();
...
iv_ship.translateXProperty().addListener(checkIntersection);
iv_ship.translateYProperty().addListener(checkIntersection);
...
root.getChildren().addAll(iv_plane,iv_ship);
primaryStage.setScene(scene_game);
}
I am reading content from file and displaying it to GUI.
Here is my file:
Log ; ytr
Thread Sleep ; 654
Log ; hgfd
Thread Sleep ; 543
Log ; hgfd
Thread Sleep ; 7654
Log ; grdr
I select a file and it reads the file and then updates the GUI simultaneously. So there is a button which lets me choose my file. The above is a sample of one of my file and I read that and if its "Log" is outputs whatever it is to the GUI.
I am doing my multithreading at the log function
UPDATE here is my entire (relevant) code:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class HelloWorld extends Application {
final static TextArea m_text_area = new TextArea();
final static GridPane m_grid = new GridPane();
final FileChooser fileChooser = new FileChooser();
static String parameters = "";
final static Scene m_scene = new Scene(m_grid, 500, 500);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Choose your file...");
m_grid.add(m_text_area, 0, 1);
m_grid.add(btn, 0, 0);
final String thread_sleep = "Thread Sleep";
final String log = "Log";
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
List<File> list = fileChooser
.showOpenMultipleDialog(primaryStage);
if (list != null) {
for (File file : list) {
if (file.isFile()) {
if (file.getName().indexOf(".") != 0) {
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(file
.getAbsolutePath().toString()));
int i = 0;
while ((sCurrentLine = br.readLine()) != null) {
if (!sCurrentLine.startsWith("#")) {
String line[] = sCurrentLine
.split(";");
String command = line[0].trim();
try {
parameters = line[1].trim();
} catch (Exception e5) {
}
switch (command) {
case thread_sleep: {
Thread.sleep(Integer
.parseInt(parameters));
break;
}
case log: {
log(parameters);
break;
}
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
}
}
});
primaryStage.setScene(m_scene);
primaryStage.show();
}
public static void log(String text) {
final String textToDisplay = text;
Platform.runLater(new Runnable() {
#Override
public void run() {
m_text_area.appendText(textToDisplay + "\n");
}
});
}
}
My issue: The GUI freezes and updates only one the whole program has been executed
You are sleeping inside the event. The GUI cannot process further events until the current event finishes. That is why the program freezes.
You need to use a background worker thread for this. There is a tutorial here.
Task<Void> task = new Task<Void>() {
#Override
protected Void call() {
// long-running task
return (Void)null;
}
};
new Thread(task).start();