I write a programm which shows a waveform by using an Areachart.When i compile it and run it it looks just fine like below.When i execute the .jar file i get a complete different view of my waveform.
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;
public class AreaChartSample extends Application {
private static final int MAX_DATA_POINTS = 500;
private Series series;
private int xSeriesData = 0;
private ConcurrentLinkedQueue<Number> dataQ = new ConcurrentLinkedQueue<>();
private ExecutorService executor;
private AddToQueue addToQueue;
private Timeline timeline2;
private NumberAxis xAxis;
private int time_counter=0;
private int [] data_array=null;
private void init(Stage primaryStage) {
String line,full_text="";
try {
BufferedReader in = new BufferedReader(new FileReader("C:/testvideo/test.txt"));
while((line=in.readLine())!= null)
{
full_text+=line;
}
data_array=new int[full_text.length()];
for(int i=0;i<full_text.length();i++)
{
data_array[i]=((int)(full_text.charAt(i)))-127;
// data_array[i]=((int)(full_text.charAt(i)))-300;
}
} catch (Exception e) {
}
xAxis = new NumberAxis(0,MAX_DATA_POINTS,MAX_DATA_POINTS/10);
xAxis.setForceZeroInRange(false);
xAxis.setAutoRanging(false);
NumberAxis yAxis = new NumberAxis(-127,127,1);
yAxis.setAutoRanging(false);
//-- Chart
final AreaChart<Number, Number> sc = new AreaChart<Number, Number>(xAxis, yAxis) {
// Override to remove symbols on each data point
#Override protected void dataItemAdded(Series<Number, Number> series, int itemIndex, Data<Number, Number> item) {}
};
sc.setAnimated(false);
sc.setId("liveAreaChart");
sc.setTitle("Animated Area Chart");
//-- Chart Series
series = new AreaChart.Series<Number, Number>();
series.setName("Area Chart Series");
sc.getData().add(series);
primaryStage.setScene(new Scene(sc));
}
#Override public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
//-- Prepare Executor Services
executor = Executors.newCachedThreadPool();
addToQueue = new AddToQueue();
executor.execute(addToQueue);
//-- Prepare Timeline
prepareTimeline();
primaryStage.setOnCloseRequest(e -> {
executor.shutdown();
});
}
public static void main(String[] args) {
launch(args);
}
private class AddToQueue implements Runnable {
public void run() {
try {
// add a item of random data to queue
dataQ.add(data_array[time_counter]);
time_counter+=100;
Thread.sleep(10);
executor.execute(this);
} catch (InterruptedException ex) {
Logger.getLogger(AreaChartSample.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//-- Timeline gets called in the JavaFX Main thread
private void prepareTimeline() {
// Every frame to take any data from queue and add to chart
new AnimationTimer() {
#Override public void handle(long now) {
addDataToSeries();
}
}.start();
}
private void addDataToSeries() {
for (int i = 0; i < 20; i++) { //-- add 20 numbers to the plot+
if (dataQ.isEmpty()) break;
Number y=dataQ.remove();
series.getData().add(new AreaChart.Data(xSeriesData++, y));
// System.out.println(y);
}
// remove points to keep us at no more than MAX_DATA_POINTS
if (series.getData().size() > MAX_DATA_POINTS) {
series.getData().remove(0, series.getData().size() - MAX_DATA_POINTS);
}
// update
xAxis.setLowerBound(xSeriesData-MAX_DATA_POINTS);
xAxis.setUpperBound(xSeriesData-1);
}
}
when i just run it =>
when i execute the build .jar file (windows 7 64 bit -> java8)
I have absolute no idea why this can happen.
Update: here is test.txt: http://expirebox.com/download/bf9be466e23c4c3d8f73f094f261dfbe.html
UPDATE2
Okay it must have to do with the reading of the file.when i change
data_array[i]=((int)(full_text.charAt(i)))-127;
to
data_array[i]=data_array[i]=((int)('f'))-127;
it is the same in both "versions".
Is there are another method which could read correct in both ways.Maybe it has to do with UTF8 or so?
This did the trick. Thank you!
String fileName = "C:/testvideo/test.txt";
FileInputStream is = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader in = new BufferedReader(isr);
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 have two classes ViewTaskTest and ControllerTaskTest. The view has two buttons, one to create a random point and the other to start the controller. After the start, the controller will place 10 random points to the chart inside the view. But the points are visible only at the end. I want to see the points being placed one by one. I know, that I have to use somehow the Task-functions and I am struggling to understand this concept.
This is the ViewTaskTest-class:
package View;
import Controller.ControllerTaskTest;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.chart.Axis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ViewTaskTest{
ScatterChart<Number, Number> scatterChart;
XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
Axis<Number> xAxis = new NumberAxis(0, 10, 2); ;
Axis<Number> yAxis = new NumberAxis(0, 10, 2); ;
Button buttonAddRandomPoint = new Button("Add random point");
Button buttonStartControllerTest = new Button("Start controller");
private final int MAIN_WINDOW_HEIGHT = 800;
private final int MAIN_WINDOW_WIDTH = 800;
ControllerTaskTest controller;
public ViewTaskTest() {
}
public void setController(ControllerTaskTest controller) {
this.controller = controller;
}
public void fillStage(Stage stage) {
stage.setTitle("QuickPID");
stage.setMinHeight(MAIN_WINDOW_HEIGHT);
stage.setMinWidth(MAIN_WINDOW_WIDTH);
stage.setMaxHeight(MAIN_WINDOW_HEIGHT);
stage.setMaxWidth(MAIN_WINDOW_WIDTH);
Scene sceneOne = new Scene(new Group());
scatterChart = new ScatterChart<Number, Number>(xAxis, yAxis);
scatterChart.getData().add(series);
// add a random point
buttonAddRandomPoint.setOnAction(e -> {
Double x = new Double(0.0);
Double y = new Double(0.0);
try{
x = Math.random() * 10;
y = Math.random() * 10;
series.getData().add(new XYChart.Data<Number, Number>(x, y));
} catch (Exception ex) {
System.out.println("Error");
}
});
buttonStartControllerTest.setOnAction(e -> {
controller.startAddingPoints();
});
VBox vboxButtons = new VBox(5);
HBox hboxMain = new HBox(5);
vboxButtons.getChildren().addAll(buttonAddRandomPoint, buttonStartControllerTest);
vboxButtons.setAlignment(Pos.BOTTOM_LEFT);
vboxButtons.setPadding(new Insets(10));
hboxMain.getChildren().addAll(scatterChart, vboxButtons);
sceneOne.setRoot(hboxMain);
stage.setScene(sceneOne);
}
public void addRandomPointFromController(Double x, Double y) {
System.out.println("starting view task");
Task<Integer> task = new Task<Integer>() {
#Override protected Integer call() throws Exception {
series.getData().add(new XYChart.Data<Number, Number>(x, y));
return 0;
}
};
task.run();
}
}
Here is the ControllerTestTask-Class:
package Controller;
import View.ViewTaskTest;
import javafx.concurrent.Task;
public class ControllerTaskTest {
ViewTaskTest view;
public ControllerTaskTest() {
}
public void setView(ViewTaskTest view) {
this.view = view;
}
public void startAddingPoints() {
System.out.println("starting controller task");
Task<Integer> task = new Task<Integer>() {
#Override protected Integer call() throws Exception {
for(int i = 0; i < 10; i++) {
Double x = Math.random() * 10;
Double y = Math.random() * 10;
view.addRandomPointFromController(x, y);
System.out.println("Adding point x = " + x + " and y = " + y);
Thread.sleep(100);
}
return 0;
}
};
task.run();
}
}
Here is the main-class:
package Test;
import Controller.ControllerTaskTest;
import View.ViewTaskTest;
import javafx.application.Application;
import javafx.stage.Stage;
public class Test extends Application{
private ViewTaskTest view= new ViewTaskTest();
private ControllerTaskTest controller = new ControllerTaskTest();
public static void main(String[] args) {
launch();
}
#Override
public void start(Stage stage) throws Exception {
view.setController(controller);
controller.setView(view);
stage.show();
view.fillStage(stage);
}
}
Some please explain me what I am doing wrong. I am experimenting with the Thread-funcitons but I cant solve my problem.
I'm developing an application using some StackedBarChart but i've found what i think is a little bug, negative values are not rendered if the animated property of the chart is set to false. Try the code below to test it, anyone know how to solve it ?
Thanks in advance.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Created by fabiofrumento on 28/04/15.
*/
public class Scratch extends Application {
private static final SimpleDateFormat ONESECOND_CHART_DATE_FORMAT = new SimpleDateFormat("HH:mm:ss",
Locale.ENGLISH);
private boolean stopThreads;
CategoryAxis xAxisActive = new CategoryAxis();
CategoryAxis xAxisReactive = new CategoryAxis();
NumberAxis yAxisActive = new NumberAxis();
NumberAxis yAxisReactive = new NumberAxis();
{
xAxisActive.setLabel("Time");
xAxisReactive.setLabel("Time");
yAxisActive.setLabel("animated = false");
yAxisReactive.setLabel("animated = true");
}
private StackedBarChart<String, Number> onesecondActiveBarChart = new StackedBarChart<String, Number>(xAxisActive,
yAxisActive);
private StackedBarChart<String, Number> onesecondReactiveBarChart = new StackedBarChart<String, Number>(xAxisReactive,
yAxisReactive);
private XYChart.Series<String, Number> onesecondActiveConsumedSerie = new XYChart.Series<>();
private XYChart.Series<String, Number> onesecondActiveGeneratedSerie = new XYChart.Series<>();
private XYChart.Series<String, Number> onesecondReactiveConsumedSerie = new XYChart.Series<>();
private XYChart.Series<String, Number> onesecondReactiveGeneratedSerie = new XYChart.Series<>();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws
Exception {
VBox root = new VBox();
initCharts();
root.getChildren()
.addAll(onesecondActiveBarChart,
onesecondReactiveBarChart);
Scene scene = new Scene(root,
1024,
768);
primaryStage.setTitle("JecomoduleUI");
primaryStage.setScene(scene);
primaryStage.setFullScreen(true);
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
stopThreads = true;
}
});
primaryStage.show();
new Thread(new Runnable() {
#Override
public void run() {
while (!stopThreads) {
try {
Thread.sleep(1000);
Platform.runLater(new Runnable() {
#Override
public void run() {
updateActiveData();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private void initCharts() {
onesecondActiveConsumedSerie.setName("Cons. W");
onesecondActiveGeneratedSerie.setName("Gen. W");
onesecondReactiveConsumedSerie.setName("Cons. VAR");
onesecondReactiveGeneratedSerie.setName("Gen.. VAR");
onesecondActiveBarChart.getData()
.addAll(onesecondActiveConsumedSerie,
onesecondActiveGeneratedSerie);
onesecondActiveBarChart.setAnimated(false);
onesecondReactiveBarChart.getData()
.addAll(onesecondReactiveConsumedSerie,
onesecondReactiveGeneratedSerie);
}
void updateActiveData() {
Date format = new Date();
Integer oneSecondActiveConsumedValue;
Integer oneSecondActiveGeneratedValue;
Double rand = Math.random();
Integer rnd = new Double(1000l + rand * 9000l).intValue();
if (rnd % 2 == 0) {
oneSecondActiveConsumedValue = rnd;
oneSecondActiveGeneratedValue = 0;
} else {
oneSecondActiveConsumedValue = 0;
oneSecondActiveGeneratedValue = 0 - rnd;
}
onesecondActiveConsumedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveConsumedValue));
if (onesecondActiveConsumedSerie.getData()
.size() > 10)
onesecondActiveConsumedSerie.getData()
.remove(0);
onesecondActiveGeneratedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveGeneratedValue));
if (onesecondActiveGeneratedSerie.getData()
.size() > 10)
onesecondActiveGeneratedSerie.getData()
.remove(0);
onesecondReactiveConsumedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveConsumedValue));
if (onesecondReactiveConsumedSerie.getData()
.size() > 10)
onesecondReactiveConsumedSerie.getData()
.remove(0);
onesecondReactiveGeneratedSerie.getData()
.add(new XYChart.Data<String, Number>(ONESECOND_CHART_DATE_FORMAT.format(format),
oneSecondActiveGeneratedValue));
if (onesecondReactiveGeneratedSerie.getData()
.size() > 10)
onesecondReactiveGeneratedSerie.getData()
.remove(0);
}
}
Yes, this seems to be a JavaFX error (Java 8u60).
Looking at the source code of StackedBarChart, an item with negative value gets drawn correctly only if "negative" is found in the style classes of the item's node (see StackedBarChart#layoutPlotChildren).
The "negative" style should be set by StackedBarChart#dataItemAdded. For animated charts StackedBarChart#animateData is called, where the "negative" style is added to the node if the item's value is negative.
For non-animated data, the node gets added to the chat's plot children without updating the style class.
As a workaround, override dataItemAdded of onesecondActiveBarChart:
private StackedBarChart<String, Number> onesecondActiveBarChart = new StackedBarChart<String, Number>(xAxisActive, yAxisActive) {
#Override
protected void dataItemAdded(XYChart.Series<String,Number> series, int itemIndex, XYChart.Data<String,Number> item) {
super.dataItemAdded(series, itemIndex, item);
Node bar = item.getNode();
double barVal = item.getYValue().doubleValue();
if (barVal < 0) {
bar.getStyleClass().add("negative");
}
}
};
I am having one code that send command to server.
public static void createAndSendCommand(String action, byte[] data) {
if (action.equals(OE_Constants.ACTION_UPDATE)) {
File file = new File(OE_Constants.FILE_BACKUP_TOPOLOGY);
Command command = ConnectionManager.populateData(file);
FrontEndClient.sendCommandToServer(command);
}
}
and
public static boolean sendCommandToServer(Command command) {
try {
outStream.writeObject(command);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
And I am receiving result like below.
public void receiveResultFromServer() {
try {
while(!clientSocket.isClosed()) {
CommandExecResult result;
try {
result = (CommandExecResult) inStream.readObject();
ConnectionManager.parseCommandExecutionResult(result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
Now I want to wait for command to be successfully executed on server till the result of it is received by client. I want to show some Progress indicator type of UI ....how to do that?
Thanks!
Use a Task or a Service for your long running server calls.
Use Task.updateProgress() to inform on the current progress / work done.
Bind the progressProperty of your running Task to a ProgressBar or ProgressIndicator.
You specified the tags java and javafx. Here is my solution for javafx. It is a simple dialog that can be updated from 'outside' via binding.
WorkingDialog.java:
package stackoverflow.progress;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public final class WorkingDialog extends Stage implements Initializable {
private static final Logger LOG = Logger.getLogger(WorkingDialog.class.getName());
public SimpleDoubleProperty progress = new SimpleDoubleProperty(0);
public WorkingDialog(String title, Stage owner) {
super();
setTitle(title);
initStyle(StageStyle.UTILITY);
initModality(Modality.APPLICATION_MODAL);
initOwner(owner);
double w = 300;
double h = 200;
setWidth(w);
setHeight(h);
double dx = (owner.getWidth() - w) / 2;
double dy = (owner.getHeight() - h) / 2;
setX(owner.xProperty().get() + dx);
setY(owner.yProperty().get() + dy);
setResizable(false);
showDialog(progress);
}
public void hideDialog() {
Platform.runLater(() -> {
hide();
});
}
public void setTitleText(String title) {
Platform.runLater(() -> {
setTitle(title);
});
}
private void showDialog(SimpleDoubleProperty progress) {
//scene : gridPane : 0,0->progressbar,0,1->borderpane : center->button
GridPane gridPane = new GridPane();
gridPane.setGridLinesVisible(false);
gridPane.setPadding(new Insets(10));
gridPane.setHgap(5);
gridPane.setVgap(5);
setOnCloseRequest((WindowEvent e) -> {
e.consume();
});
ProgressBar pb = new ProgressBar(-1);
pb.setPrefWidth(300);
pb.progressProperty().bind(progress);
BorderPane borderPane = new BorderPane(pb);
gridPane.add(borderPane, 0, 0);
Scene scene = new Scene(gridPane);
setScene(scene);
sizeToScene();
show();
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
}
Example for usage (WorkingDialogTest.java):
package stackoverflow.progress;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class WorkingDialogTest extends Application {
private static final Logger LOG = Logger.getLogger(WorkingDialogTest.class.getName());
#Override
public void start(Stage primaryStage) {
Group group = new Group();
Scene scene = new Scene(group);
primaryStage.setTitle("Dialogs");
primaryStage.setWidth(600);
primaryStage.setHeight(400);
Button button = new Button("function");
button.setOnAction((ActionEvent e) -> {
WorkingDialog wd = new WorkingDialog("title", primaryStage);
new Thread(() -> {
int counter = 10;
for (int i = 0; i < counter; i++) {
try {
wd.progress.set(1.0 * i / (counter - 1));
Thread.sleep(1000); //<-------- do more useful stuff here
} catch (InterruptedException ex) {
}
}
wd.hideDialog();
}).start();
});
HBox hbox = new HBox(button);
group.getChildren().addAll(hbox);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
It looks like this:
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();