Call thread from another thread javafx - multithreading

I have been trying to run two tasks on two threads and using their progress to be indicated on progress bar and progress indicator.
First task is copyTask and second is copy file.
The copyTask sends the file object to copyFile for file copy.
But the problem is only a single file gets copied and the file count seems to be correct.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.CountDownLatch;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextArea;
/**
* FXML Controller class
*
* #author ANIL
*/
public class ProgressIndicateController implements Initializable {
#FXML
private ProgressIndicator uploadIndicator;
#FXML
private ProgressBar uploadBar;
#FXML
private TextArea errTxt;
#FXML
private Label uploadTxt;
File f;
Thread parent,child;
CountDownLatch latch = new CountDownLatch(1);
#FXML
private Label sizeTXT;
// private CopyTask copyTask;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
// Unbind progress property
uploadBar.progressProperty().unbind();
// Bind progress property
uploadBar.progressProperty().bind(copyFile.progressProperty());
// Hủy bỏ kết nối thuộc tính progress
uploadIndicator.progressProperty().unbind();
// Bind progress property.
uploadIndicator.progressProperty().bind(copyTask.progressProperty());
// Unbind text property for Label.
uploadTxt.textProperty().unbind();
// Bind the text property of Label
// with message property of Task
uploadTxt.textProperty().bind(copyTask.messageProperty());
// Unbind text property for Label.
sizeTXT.textProperty().unbind();
// Bind the text property of Label
// with message property of Task
sizeTXT.textProperty().bind(copyFile.messageProperty());
// When completed tasks
copyTask.addEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, //
new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t) {
List<File> copied = copyTask.getValue();
uploadTxt.textProperty().unbind();
uploadTxt.setText("Copied: " + copied.size());
}
});
copyFile.addEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED, //
new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t) {
File copied = copyFile.getValue();
sizeTXT.textProperty().unbind();
sizeTXT.setText("Copied: " + copied.getAbsolutePath());
}
});
// Start the Task.
parent= new Thread(copyTask);
parent.start();
}
Task<List<File>> copyTask = new Task<List<File>>() {
#Override
protected List<File> call() throws Exception {
File dir = new File("F:");
File[] files = dir.listFiles();
int count = files.length;
List<File> copied = new ArrayList<File>();
int i = 0;
for (File file : files) {
if (file.isFile()) {
this.copy(file);
copied.add(file);
}
i++;
this.updateProgress(i, count);
}
return copied;
}
private void copy(File file) throws Exception {
this.updateMessage("Copying: " + file.getAbsolutePath());
f = file;
child=new Thread(copyFile);
child.start();
this.wait();
}
};
Task<File> copyFile = new Task<File>() {
#Override
protected File call() throws Exception {
InputStream is = null;
OutputStream os = null;
File dest=null;
String name=f.getName();
dest=new File("D:\\OUTPUT\\"+name);
is = new FileInputStream(f);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
double i=0.0;
double l=f.length();
while ((length = is.read(buffer)) > 0) {
i+=length;
this.updateMessage("Copying: " + i +" bytes of " + l);
os.write(buffer, 0, length);
this.updateProgress(i, l);
Thread.sleep(500);
}
is.close();
os.close();
this.notifyAll();
return dest;
}
};
}
New Code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.CyclicBarrier;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextArea;
/**
* FXML Controller class
*
* #author ANIL
*/
public class ProgressIndicateController implements Initializable {
#FXML
private ProgressIndicator uploadIndicator;
#FXML
private ProgressBar uploadBar;
#FXML
private TextArea errTxt;
#FXML
private Label uploadTxt;
#FXML
private Label sizeTXT;
CyclicBarrier cb = new CyclicBarrier(2);
final SimpleDoubleProperty prog1 = new SimpleDoubleProperty(0);
final SimpleDoubleProperty prog2 = new SimpleDoubleProperty(0);
final SimpleStringProperty text1 = new SimpleStringProperty("");
final SimpleStringProperty text2 = new SimpleStringProperty("");
final SimpleStringProperty err = new SimpleStringProperty("");
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
// Unbind progress property
uploadBar.progressProperty().unbind();
// Bind progress property
uploadBar.progressProperty().bind(prog2);
// Hủy bỏ kết nối thuộc tính progress
uploadIndicator.progressProperty().unbind();
// Bind progress property.
uploadIndicator.progressProperty().bind(prog1);
// Unbind text property for Label.
uploadTxt.textProperty().unbind();
// Bind the text property of Label
// with message property of Task
uploadTxt.textProperty().bind(text1);
// Unbind text property for Label.
sizeTXT.textProperty().unbind();
// Bind the text property of Label
// with message property of Task
sizeTXT.textProperty().bind(text2);
//When completed tasks
errTxt.textProperty().unbind();
errTxt.textProperty().bind(err);
// Start the Task.
new Thread() {
#Override
public void run() {
File dir = new File("F:");
File[] files = dir.listFiles();
int count = files.length;
int i = 0;
for (File file : files) {
if (file.isFile()) {
try {
text1.setValue("Copying: " + file.getAbsolutePath());
InputStream is = null;
OutputStream os = null;
File dest = null;
String name = file.getName();
dest = new File("D:\\OUTPUT\\" + name);
is = new FileInputStream(file);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
double j = 0.0;
double l = file.length();
while ((length = is.read(buffer)) > 0) {
j += length;
text2.setValue("Copying: " + j + " bytes of " + l);
os.write(buffer, 0, length);
prog2.setValue(j / l);
Thread.sleep(100);
}
is.close();
os.close();
} catch (Exception ex) {
err.setValue(ex.toString());
}
i++;
prog1.setValue(i / count);
}
}
}
}.start();
}
}

Related

Trying to render a square with vaos and vbos

i am trying to learn how to use vaos and vbos. Right now i am trying to render a square but nothing is rendering on the screen. I am using android studios and OpenGL ES 3.
This is my MainActivity:
package com.example.karno.androidgameprojectv3;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import renderEngine.DisplayManager;
import renderEngine.MainRenderer;
public class MainActivity extends Activity {
DisplayManager gameView;
MainRenderer renderer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
renderer = new MainRenderer();
gameView = new DisplayManager(this);
gameView.setEGLContextClientVersion(3);
gameView.setRenderer(renderer);
this.setContentView(gameView);
}
#Override
protected void onDestroy(){
// Log.d("------test", "in on destroy");
renderer.loader.cleanUp();
super.onDestroy();
}
}
This is the Loader class where i bind the vaos and vbos:
package renderEngine;
import android.opengl.GLES11;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.util.Log;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class Loader {
private int [] vaos;
private int [] vbos;
private int countVbos = -1;
private int countVaos = -1;
public Loader( int neededVAOs, int neededVBOs){
vaos = new int[neededVAOs];
vbos = new int[neededVBOs];
}
public RawModel loadToVAO(float[] position) {
int vaoID = createVAO();
storeDataInAttributeList(0, 3, position);
unbindVAO();
Log.d("looking for null---", "position = " + position);
return new RawModel(vaoID, position.length/3);
}
private int createVAO() {
countVaos++;
GLES30.glGenVertexArrays(1, vaos, 0);
GLES30.glBindVertexArray(vaos[countVaos]);
return vaos[countVaos];
}
private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float[] data) {
countVbos++;
// GLES30.glGenBuffers(1, vbos);
GLES20.glGenBuffers(1, vbos,0);
// Log.d("------vbo", "vbo id = " + vbos.get(countVbos));
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbos[countVbos]);
FloatBuffer buffer = storeDataInFloatBuffer(data);
// Log.d("looking for null arg", "arg2 = " + vbos.get(countVbos) + ", arg3 = " + buffer);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vbos[0], buffer, GLES30.GL_STATIC_DRAW);
GLES30.glVertexAttribPointer(attributeNumber, coordinateSize, GLES30.GL_FLOAT, false, 0, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
}
private FloatBuffer storeDataInFloatBuffer(float[] data) {
FloatBuffer buffer = FloatBuffer.allocate(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
private void unbindVAO() {
// this will unbind the VAO
GLES30.glBindVertexArray(0);
}
public void cleanUp() {
Log.d("--------", "in clean up");
for (int vao : vaos) {
GLES30.glDeleteBuffers(vao, vaos, 0);
}
countVaos = -1;
for (int vbo : vbos) {
GLES20.glDeleteBuffers(vbo, vbos,0);
}
countVbos = -1;
Log.d("--------", "cleaned up.");
}
}
The MainRenderer:
package renderEngine;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MainRenderer implements GLSurfaceView.Renderer {
public Loader loader;
Renderer renderer;
RawModel model;
private static final int NEEDED_VAOS = 1;
private static final int NEEDED_VBOS = 1;
//square
float[] vertecies = {
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f,
};
#Override
public void onDrawFrame(GL10 arg0){
// GLES20.glClearColor(0,1,0,1);
// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
renderer.prepare();
renderer.render(model);
}
#Override
public void onSurfaceChanged(GL10 arg0, int height, int width){
}
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config){
// Log.d("check------", "in on surface created.");
loader = new Loader(NEEDED_VAOS, NEEDED_VBOS);
renderer = new Renderer();
model = loader.loadToVAO(vertecies);
}
}
The View:
package renderEngine;
import android.content.Context;
import android.opengl.GLSurfaceView;
public class DisplayManager extends GLSurfaceView {
public DisplayManager(Context context){
super(context);
}
}
The Render class:
package renderEngine;
import android.opengl.GLES11;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.util.Log;
public class Renderer {
public void prepare(){
GLES11.glClearColor(0,1,0,1);
GLES11.glClear(GLES11.GL_COLOR_BUFFER_BIT);
}
public void render(RawModel model) {
// Log.d("------render","model.getVaoID() = "+ model.getVaoID());
GLES30.glBindVertexArray(model.getVaoID());
GLES30.glEnableVertexAttribArray(0);
GLES11.glDrawArrays(GLES11.GL_TRIANGLES, 0, model.getVertexCount());
GLES20.glDisableVertexAttribArray(0);
GLES30.glBindVertexArray(0);
}
}
The 3d model.
package renderEngine;
public class RawModel
{
private int vaoID;
private int vertexCount;
public RawModel(int vaoID, int vertexCount)
{
this.vaoID = vaoID;
this.vertexCount = vertexCount;
}
/**
* #return the vaoID
*/
public int getVaoID() {
return vaoID;
}
/**
* #return the vertexCount
*/
public int getVertexCount() {
return vertexCount;
}
}
In logcat i am getting:
2019-01-06 20:33:43.667 4618-4657/com.example.karno.androidgameprojectv3 E/emuglGLESv2_enc: a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=0x7c2911e22a00
2019-01-06 20:33:43.667 4618-4657/com.example.karno.androidgameprojectv3 E/emuglGLESv2_enc: Out of bounds vertex attribute info: clientArray? 0 attribute 0 vbo 1 allocedBufferSize 1 bufferDataSpecified? 1 wantedStart 0 wantedEnd 72
Any help will be appreciated.
The 2nd parameter of GLES30.glBufferData has to be the size of the buffer in bytes, rather then the named buffer object.
See also Java Code Examples for android.opengl.GLES20.glBufferData() and glBufferData:
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,
buffer.capacity() * BYTES_PER_FLOAT, buffer, GLES30.GL_STATIC_DRAW);
Note glBufferData creates and initializes the buffer object's data store, for the buffer object which is currently bound by glBindBuffer.

JavaFX - How to resize a SVG Path right in a TableView

I'm having issues to render a SVG Image in a TableView with a CellFactory.
Im using this code here, but it don't work, the svg image is scaled, but it don't resize.
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.shape.SVGPath;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class SVGTable extends Application {
private ObservableList<SVGExample> examples;
public static void main(String[] args) {
launch(args);
}
public SVGTable() {
examples = FXCollections.observableArrayList();
examples.addAll(new SVGExample(289),
new SVGExample(42),
new SVGExample(120));
}
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane pane = new AnchorPane();
Scene scene = new Scene(pane);
TableView<SVGExample> tableView = new TableView<>();
tableView.setMinWidth(500);
tableView.setMinHeight(400);
tableView.setItems(examples);
final TableColumn<SVGExample, Integer> ping = new TableColumn<>("Ping");
ping.setCellValueFactory(new PropertyValueFactory<>("ping"));
ping.setCellFactory(param -> new PingCell());
tableView.getColumns().add(ping);
pane.getChildren().add(tableView);
primaryStage.setScene(scene);
primaryStage.show();
}
public class SVGExample {
private final IntegerProperty ping = new SimpleIntegerProperty();
public SVGExample(int ping) {
setPing(ping);
}
public int getPing() {
return ping.get();
}
public IntegerProperty pingProperty() {
return ping;
}
public void setPing(int ping) {
this.ping.set(ping);
}
}
public class PingCell extends TableCell<SVGExample, Integer> {
private HBox hBox = new HBox();
private Label label;
private int oldValue;
private PingCell() {
label = new Label();
hBox.setAlignment(Pos.CENTER_LEFT);
oldValue = Integer.MIN_VALUE;
}
#Override
protected void updateItem(final Integer item, final boolean empty) {
if (item != null) {
label.setText(item + "ms");
int i = (item + 50) / 100;
if (i < 1)
i = 1;
if (4 < i)
i = 4;
if (i != oldValue) {
SVGPath svgPath1 = new SVGPath();
svgPath1.setContent("M149.2,8.3L127-13.9c42.4-42.4,98.7-65.8,158.5-65.8c59.8,0,116.1,23.4,158.5,65.8L421.8,8.3c-36.5-36.5-84.9-56.6-136.3-56.6C234.1-48.2,185.7-28.1,149.2,8.3z");
SVGPath svgPath2 = new SVGPath();
svgPath2.setContent("M190.9,50.1l-22.2-22.2C200-3.4,241.4-20.6,285.5-20.6c44.1,0,85.5,17.2,116.8,48.4l-22.2,22.2c-25.3-25.3-58.9-39.2-94.6-39.2C249.8,10.8,216.2,24.8,190.9,50.1z");
SVGPath svgPath3 = new SVGPath();
svgPath3.setContent("M232.7,91.8l-22.2-22.2c20.1-20.1,46.7-31.1,75-31.1s55,11.1,75,31.1l-22.2,22.2c-14.1-14.1-32.9-21.9-52.8-21.9C265.6,69.9,246.8,77.7,232.7,91.8z");
SVGPath svgPath4 = new SVGPath();
svgPath4.setContent("M285.5,98.1c-12.8,0-24.5,5.2-32.9,13.6l32.9,32.9l32.9-32.9C310,103.3,298.3,98.1,285.5,98.1z");
Shape s = SVGPath.union(SVGPath.union(SVGPath.union(svgPath1, svgPath2), svgPath3), svgPath4);
s.setScaleX(0.1);
s.setScaleY(0.1);
hBox.getChildren().clear();
hBox.getChildren().addAll(s, label);
}
setGraphic(hBox);
}
}
}
}
After run, it's look like this:
You can wrap the Shape in a Group to force re-size of layout bounds.
hBox.getChildren().addAll(new Group(s), label);
Scale is a type of transform and according to Javadocs:
Any transform, effect, or state applied to a Group will be applied to all children of that group. Such transforms and effects will NOT be included in this Group's layout bounds, however if transforms and effects are set directly on children of this Group, those will be included in this Group's layout bounds.

JavaFX: Adding rows to TableView with a HashMap binding

Suppose that I have a map collection:
ObserableHashMap<K,V> map = FXCollections.observableHashMap();
I put 1 record into this map during fxml controller initialization, then wrap it as ObservableList:
ObservableList<ObserableHashMap.Entry<K,V>> list = FXCollections.observableArrayList(map.entrySet());
then setitems for my tableView.setItems(list);
Everything is fine when I run this JavaFX app and 1 record is showing.
Question is that:
When I add more records later to my map, my TableView will not refresh these records.
How could I bind a dynamical map collection into my TableView?
Thanks
If you use an ObservableList of ObservableMaps as your TableView's data structure
ObservableList<ObservableMap> rowMaps = FXCollections.observableArrayList();
tableView.setItems(rowMaps);
and implement your own ObservableMapValueFactory
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.util.Callback;
public class ObservableMapValueFactory<V> implements
Callback<TableColumn.CellDataFeatures<ObservableMap, V>, ObservableValue<V>> {
private final Object key;
public ObservableMapValueFactory(Object key) {
this.key = key;
}
#Override
public ObservableValue<V> call(CellDataFeatures<ObservableMap, V> features) {
final ObservableMap map = features.getValue();
final ObjectProperty<V> property = new SimpleObjectProperty<V>((V) map.get(key));
map.addListener(new MapChangeListener<Object, V>() {
public void onChanged(Change<?, ? extends V> change) {
if (key.equals(change.getKey())) {
property.set((V) map.get(key));
}
}
});
return property;
}
}
and then set it as the cell value factory for your column(s)
column.setCellValueFactory(new ObservableMapValueFactory<String>(columnId));
all changes to your data are reflected in the TableView, even changes only affecting the ObservableMaps.
You can bind a map directly to a TableView, consider this example from the JavaFX documentation :
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class TableViewSample extends Application {
public static final String Column1MapKey = "A";
public static final String Column2MapKey = "B";
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
stage.setWidth(300);
stage.setHeight(500);
final Label label = new Label("Student IDs");
label.setFont(new Font("Arial", 20));
TableColumn<Map, String> firstDataColumn = new TableColumn<>("Class A");
TableColumn<Map, String> secondDataColumn = new TableColumn<>("Class B");
firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));
firstDataColumn.setMinWidth(130);
secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));
secondDataColumn.setMinWidth(130);
TableView table_view = new TableView<>(generateDataInMap());
table_view.setEditable(true);
table_view.getSelectionModel().setCellSelectionEnabled(true);
table_view.getColumns().setAll(firstDataColumn, secondDataColumn);
Callback<TableColumn<Map, String>, TableCell<Map, String>>
cellFactoryForMap = new Callback<TableColumn<Map, String>,
TableCell<Map, String>>() {
#Override
public TableCell call(TableColumn p) {
return new TextFieldTableCell(new StringConverter() {
#Override
public String toString(Object t) {
return t.toString();
}
#Override
public Object fromString(String string) {
return string;
}
});
}
};
firstDataColumn.setCellFactory(cellFactoryForMap);
secondDataColumn.setCellFactory(cellFactoryForMap);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table_view);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
private ObservableList<Map> generateDataInMap() {
int max = 10;
ObservableList<Map> allData = FXCollections.observableArrayList();
for (int i = 1; i < max; i++) {
Map<String, String> dataRow = new HashMap<>();
String value1 = "A" + i;
String value2 = "B" + i;
dataRow.put(Column1MapKey, value1);
dataRow.put(Column2MapKey, value2);
allData.add(dataRow);
}
return allData;
}
}
More information can be found here
The answer from ItachiUchiha use the columns as keys and the rows as individual maps. If you'd like one map with the rows as keys->values, you'll have to add a listener to the map that will change the list when you add or delete. I did something similar here. https://stackoverflow.com/a/21339428/2855515

I am getting a NullPointerException when trying to use the Service class

I am getting a NullPointerException which is as follows:
java.lang.NullPointerException
file:/K:/Learner/JavaFx2/ProductApplication/dist/run166129449/ProductApplication.jar!/com/product/app/view/viewsingle.fxml
at com.product.app.controller.ViewSingleController.initialize(ViewSingleController.java:70)
at javafx.fxml.FXMLLoader.load(Unknown Source)
at javafx.fxml.FXMLLoader.load(Unknown Source)
And my ViewSingleController is as follows:
package com.product.app.controller;
import com.product.app.model.Product;
import com.product.app.service.ViewProductsService;
import com.product.app.util.JSONParser;
import com.product.app.util.TagConstants;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
import javax.swing.JOptionPane;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* FXML Controller class
*
* #author Arun Joseph
*/
public class ViewSingleController implements Initializable {
private static String action = "";
#FXML
private TextField txtID;
#FXML
private TextField txtName;
#FXML
private TextField txtPrice;
#FXML
private TextArea txtDesc;
#FXML
private Region veil;
#FXML
private ProgressIndicator p;
private ViewProductsService service = new ViewProductsService();
private JSONObject product = null;
private JSONParser parser = new JSONParser();
private int pid = 1;
public void setPid(int pid) {
this.pid = pid;
}
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
p.setMaxSize(150, 150);
p.progressProperty().bind(service.progressProperty());
veil.visibleProperty().bind(service.runningProperty());
p.visibleProperty().bind(service.runningProperty());
Product product = new Product();
service.start();
ObservableList<Product> products = service.valueProperty().get();
products.get(pid);
txtID.textProperty().set(String.valueOf(products.get(pid).getPid()));
//product = service.valueProperty().get().get(pid);
//txtID.setText(String.valueOf(product.getPid()));
txtName.textProperty().set(product.getName());
txtPrice.textProperty().set(String.valueOf(product.getPrize()));
txtDesc.textProperty().set(product.getDescription());
}
private SomeService someService = new SomeService();
#FXML
private void handleUpdateButtonClick(ActionEvent event) {
action = "update";
someService.start();
p.progressProperty().bind(service.progressProperty());
veil.visibleProperty().bind(service.runningProperty());
p.visibleProperty().bind(service.runningProperty());
}
#FXML
private void handleDeleteButtonClick(ActionEvent event) {
action = "delete";
someService.start();
p.progressProperty().bind(service.progressProperty());
veil.visibleProperty().bind(service.runningProperty());
p.visibleProperty().bind(service.runningProperty());
}
#FXML
private void handleCancelButtonClick(ActionEvent event) {
closeStage();
}
private void closeStage() {
ViewSingleController.stage.close();
}
private static Stage stage = null;
public static void setStage(Stage stage) {
ViewSingleController.stage = stage;
}
private class SomeService extends Service<String> {
#Override
protected Task<String> createTask() {
return new SomeTask();
}
private class SomeTask extends Task<String> {
#Override
protected String call() throws Exception {
String result = "";
int success = 0;
List<NameValuePair> params = new ArrayList<NameValuePair>();
switch (action) {
case "update":
params.add(new BasicNameValuePair("pid", txtID.getText()));
params.add(new BasicNameValuePair("name", txtName.getText()));
params.add(new BasicNameValuePair("price", txtPrice.getText()));
params.add(new BasicNameValuePair("description", txtDesc.getText()));
product = parser.makeHttpRequest(TagConstants.url_update_product_with_id, "POST", params);
success = product.getInt(TagConstants.TAG_SUCCESS);
if (success == 1) {
result = "Successfully Updated the product";
JOptionPane.showMessageDialog(null, result);
closeStage();
}
break;
case "delete":
params.add(new BasicNameValuePair("pid", txtID.getText()));
product = parser.makeHttpRequest(TagConstants.url_delete_product_with_id, "POST", params);
success = product.getInt(TagConstants.TAG_SUCCESS);
if (success == 1) {
result = "Successfully Deleted the product";
JOptionPane.showMessageDialog(null, result);
closeStage();
}
break;
}
return result;
}
}
}
}
Please help me on how to fix this null pointer problem really help required. Thank you in advance
Inspect the line ViewSingleController.java:70. Put a breakpoint there. Run the program in a debugger and see what variables/fields are null.
The Exception happens on line 70, as you can see from the StackTrace.
On line 70, you call:
txtPrice.textProperty().set(String.valueOf(product.getPrize()));
The NullPointerException means that you are trying to access a method of an object that does not exist. Here, this might be txtPrice, textProperty, product or getPrize.
Skimming over your code, I'd guess it might be txtPrice, because you only set it as a member variable via
private TextField txtPrice;
but you never initialize it. Thus, txtPrice is null and txtPrice.textProperty().set will probably throw the NullPointer.

How do I implement JavaFX in existing WindowBuilder project ?

I am trying to get my head around the JavaFX stuff...
My program is a WindowBuilder based Gui, and I want a JavaFX graph, and a JavaFX live video-feed displayed in my app.
How do I implement it in my code? I have tried this, but I couldn't get it runnning.
The data feed isnt the problem. I just need to view it inside my JFrame as small squares...
Confused now :(
Here is my code: (I am sorry that it is a tad long, but I blame the examplecode from JavaFX :p
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import java.awt.Canvas;
import java.awt.SystemColor;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import javax.swing.UIManager.*;
/**
* #author
*
*/
public class MyClientApp extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
protected static final String BufferedWriter = null;
JFrame frame;
private JTextField textFieldUsername;
/**
* Create the application.
*/
public MyClientApp(BufferedWriter serverDataOut, BufferedReader serverDataIn) {
initialize();
}
/**
* Initialize the contents of the frame.
*
* #param serverDataOut
*
*/
private void initialize() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// Nimbus Theme not avaliable
}
frame = new JFrame();
frame.setResizable(false);
frame.setTitle("*********** My Program ***********");
frame.setBounds(320, 130, 730, 570);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
Canvas canvasTemp = new Canvas();
canvasTemp.setBackground(SystemColor.window);
canvasTemp.setBounds(6, 277, 380, 255);
frame.getContentPane().add(canvasTemp);
Canvas canvasLevel = new Canvas();
canvasLevel.setBackground(SystemColor.window);
canvasLevel.setBounds(6, 10, 380, 255);
frame.getContentPane().add(canvasLevel);
}
public JFrame frame() {
return frame;
}
}
And here is the main file to get it running for you guys... :
Client.java
import java.io.IOException;
public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
MyClientApp window = new MyClientApp(null, null);
window.frame.setVisible(true);
}
}
The code I want to implement is:
AdvancedLineChartSample.java (from JavaFX)
/**
* Copyright (c) 2008, 2012 Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*/
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.util.Duration;
/**
* An advanced line chart with a variety of actions and settable properties.
*
* #see javafx.scene.chart.LineChart
* #see javafx.scene.chart.Chart
* #see javafx.scene.chart.NumberAxis
* #see javafx.scene.chart.XYChart
*/
public class AdvancedLineChartSample extends Application {
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setScene(new Scene(root));
root.getChildren().add(createChart());
}
protected LineChart<Number, Number> createChart() {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number,Number> lc = new LineChart<Number,Number>(xAxis,yAxis);
// setup chart
lc.setTitle("Temp Chart");
xAxis.setLabel("tid");
yAxis.setLabel("temp");
// add starting data
XYChart.Series<Number,Number> series = new XYChart.Series<Number,Number>();
series.setName("Dataset 1");
series.getData().add(new XYChart.Data<Number,Number>(20d, 50d));
series.getData().add(new XYChart.Data<Number,Number>(40d, 80d));
series.getData().add(new XYChart.Data<Number,Number>(50d, 90d));
series.getData().add(new XYChart.Data<Number,Number>(70d, 30d));
series.getData().add(new XYChart.Data<Number,Number>(170d, 122d));
lc.getData().add(series);
return lc;
}
#Override public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
}
public static void main(String[] args) { launch(args);
}
}
and the StreamingMediaPlayer.java (from JavaFX):
/**
* Copyright (c) 2008, 2012 Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*/
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView;
import javafx.util.Duration;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.animation.ParallelTransition;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
/**
* A media player with controls for play, pause, stop, seek, and volume. This media player is playing media via HTTP Live Streaming, also known as HLS.
*
* #see javafx.scene.media.MediaPlayer
* #see javafx.scene.media.Media
*/
public class StreamingMediaPlayer extends Application {
private static final String MEDIA_URL = "http://download.oracle.com/otndocs/products/javafx/JavaRap/prog_index.m3u8";
private MediaPlayer mediaPlayer;
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setScene(new Scene(root));
mediaPlayer = new MediaPlayer(new Media(MEDIA_URL));
mediaPlayer.setAutoPlay(true);
PlayerPane playerPane = new PlayerPane(mediaPlayer);
playerPane.setMinSize(480, 360);
playerPane.setPrefSize(480, 360);
playerPane.setMaxSize(480, 360);
// getStylesheets().add("ensemble/samples/media/OverlayMediaPlayer.css");
root.getChildren().add(playerPane);
}
public void play() {
Status status = mediaPlayer.getStatus();
if (status == Status.UNKNOWN || status == Status.HALTED) {
return;
}
if (status == Status.PAUSED || status == Status.STOPPED || status == Status.READY) {
mediaPlayer.play();
}
}
#Override public void stop() {
mediaPlayer.stop();
}
static class PlayerPane extends BorderPane {
private MediaPlayer mp;
private MediaView mediaView;
private final boolean repeat = false;
private boolean stopRequested = false;
private boolean atEndOfMedia = false;
private Duration duration;
private Slider timeSlider;
private Label playTime;
private Slider volumeSlider;
private HBox mediaTopBar;
private HBox mediaBottomBar;
private ParallelTransition transition = null;
#Override protected void layoutChildren() {
if (mediaView != null && getBottom() != null) {
mediaView.setFitWidth(getWidth());
mediaView.setFitHeight(getHeight() - getBottom().prefHeight(-1));
}
super.layoutChildren();
if (mediaView != null) {
mediaView.setTranslateX((((Pane)getCenter()).getWidth() - mediaView.prefWidth(-1)) / 2);
mediaView.setTranslateY((((Pane)getCenter()).getHeight() - mediaView.prefHeight(-1)) / 2);
}
}
#Override protected double computeMinWidth(double height) {
return mediaBottomBar.prefWidth(-1);
}
#Override protected double computeMinHeight(double width) {
return 200;
}
#Override protected double computePrefWidth(double height) {
return Math.max(mp.getMedia().getWidth(), mediaBottomBar.prefWidth(height));
}
#Override protected double computePrefHeight(double width) {
return mp.getMedia().getHeight() + mediaBottomBar.prefHeight(width);
}
#Override protected double computeMaxWidth(double height) { return Double.MAX_VALUE; }
#Override protected double computeMaxHeight(double width) { return Double.MAX_VALUE; }
public PlayerPane(final MediaPlayer mp) {
this.mp = mp;
setId("player-pane");
mediaView = new MediaView(mp);
Pane mvPane = new Pane() { };
mvPane.setId("media-pane");
mvPane.getChildren().add(mediaView);
setCenter(mvPane);
mediaTopBar = HBoxBuilder.create()
.padding(new Insets(5, 10, 5, 10))
.alignment(Pos.CENTER)
.opacity(1)
.build();
BorderPane.setAlignment(mediaTopBar, Pos.CENTER);
mediaBottomBar = HBoxBuilder.create()
.padding(new Insets(5, 10, 5, 10))
.alignment(Pos.CENTER)
.opacity(1)
.build();
BorderPane.setAlignment(mediaBottomBar, Pos.CENTER);
mp.currentTimeProperty().addListener(new ChangeListener<Duration>() {
#Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
updateValues();
}
});
mp.setOnPlaying(new Runnable() {
public void run() {
if (stopRequested) {
mp.pause();
stopRequested = false;
}
}
});
mp.setOnReady(new Runnable() {
public void run() {
duration = mp.getMedia().getDuration();
updateValues();
}
});
mp.setOnEndOfMedia(new Runnable() {
public void run() {
if (!repeat) {
stopRequested = true;
atEndOfMedia = true;
}
}
});
mp.setCycleCount(repeat ? MediaPlayer.INDEFINITE : 1);
// Time label
Label timeLabel = LabelBuilder.create()
.text("Time")
.minWidth(Control.USE_PREF_SIZE)
.textFill(Color.WHITE)
.build();
mediaTopBar.getChildren().add(timeLabel);
// Time slider
timeSlider = SliderBuilder.create()
.id("media-slider")
.minWidth(240)
.maxWidth(Double.MAX_VALUE)
.build();
timeSlider.valueProperty().addListener(new InvalidationListener() {
public void invalidated(Observable ov) {
if (timeSlider.isValueChanging()) {
// multiply duration by percentage calculated by slider position
if (duration != null) {
mp.seek(duration.multiply(timeSlider.getValue() / 100.0));
}
updateValues();
}
}
});
HBox.setHgrow(timeSlider, Priority.ALWAYS);
mediaTopBar.getChildren().add(timeSlider);
// Play label
playTime = LabelBuilder.create()
.prefWidth(130)
.minWidth(50)
.textFill(Color.WHITE)
.build();
mediaTopBar.getChildren().add(playTime);
// Volume label
Label volumeLabel = LabelBuilder.create()
.text("Vol")
.textFill(Color.WHITE)
.minWidth(Control.USE_PREF_SIZE)
.build();
mediaTopBar.getChildren().add(volumeLabel);
// Volume slider
volumeSlider = SliderBuilder.create()
.id("media-slider")
.prefWidth(120)
.maxWidth(Region.USE_PREF_SIZE)
.minWidth(30)
.build();
volumeSlider.valueProperty().addListener(new InvalidationListener() {
public void invalidated(Observable ov) {
}
});
volumeSlider.valueProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (volumeSlider.isValueChanging()) {
mp.setVolume(volumeSlider.getValue() / 100.0);
}
}
});
mediaTopBar.getChildren().add(volumeSlider);
setTop(mediaTopBar);
final EventHandler<ActionEvent> backAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.seek(Duration.ZERO);
}
};
final EventHandler<ActionEvent> stopAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.stop();
}
};
final EventHandler<ActionEvent> playAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.play();
}
};
final EventHandler<ActionEvent> pauseAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.pause();
}
};
final EventHandler<ActionEvent> forwardAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
Duration currentTime = mp.getCurrentTime();
mp.seek(Duration.seconds(currentTime.toSeconds() + 5.0));
}
};
mediaBottomBar = HBoxBuilder.create()
.id("bottom")
.spacing(0)
.alignment(Pos.CENTER)
.children(
ButtonBuilder.create()
.id("back-button")
.text("Back")
.onAction(backAction)
.build(),
ButtonBuilder.create()
.id("stop-button")
.text("Stop")
.onAction(stopAction)
.build(),
ButtonBuilder.create()
.id("play-button")
.text("Play")
.onAction(playAction)
.build(),
ButtonBuilder.create()
.id("pause-button")
.text("Pause")
.onAction(pauseAction)
.build(),
ButtonBuilder.create()
.id("forward-button")
.text("Forward")
.onAction(forwardAction)
.build()
)
.build();
setBottom(mediaBottomBar);
}
protected void updateValues() {
if (playTime != null && timeSlider != null && volumeSlider != null && duration != null) {
Platform.runLater(new Runnable() {
public void run() {
Duration currentTime = mp.getCurrentTime();
playTime.setText(formatTime(currentTime, duration));
timeSlider.setDisable(duration.isUnknown());
if (!timeSlider.isDisabled() && duration. greaterThan(Duration.ZERO) && !timeSlider.isValueChanging()) {
timeSlider.setValue(currentTime.divide(duration).toMillis() * 100.0);
}
if (!volumeSlider.isValueChanging()) {
volumeSlider.setValue((int) Math.round(mp.getVolume() * 100));
}
}
});
}
}
private static String formatTime(Duration elapsed, Duration duration) {
int intElapsed = (int)Math.floor(elapsed.toSeconds());
int elapsedHours = intElapsed / (60 * 60);
if (elapsedHours > 0) {
intElapsed -= elapsedHours * 60 * 60;
}
int elapsedMinutes = intElapsed / 60;
int elapsedSeconds = intElapsed - elapsedHours * 60 * 60 - elapsedMinutes * 60;
if (duration.greaterThan(Duration.ZERO)) {
int intDuration = (int)Math.floor(duration.toSeconds());
int durationHours = intDuration / (60 * 60);
if (durationHours > 0) {
intDuration -= durationHours * 60 * 60;
}
int durationMinutes = intDuration / 60;
int durationSeconds = intDuration - durationHours * 60 * 60 - durationMinutes * 60;
if (durationHours > 0) {
return String.format("%d:%02d:%02d",
elapsedHours, elapsedMinutes, elapsedSeconds);
} else {
return String.format("%02d:%02d",
elapsedMinutes, elapsedSeconds);
}
} else {
if (elapsedHours > 0) {
return String.format("%d:%02d:%02d",
elapsedHours, elapsedMinutes, elapsedSeconds);
} else {
return String.format("%02d:%02d",
elapsedMinutes, elapsedSeconds);
}
}
}
}
#Override public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
play();
}
public static void main(String[] args) { launch(args);
}
}
I'm sorry about the long code. Its just the samplecode from JavaFX. You find it here, and here.
That should be quite easy to solve. Let me explain it with the chart example that you've shown.
Add an instance of JFXPanel to your JFrame. In your examples, all components are added to a Stage, which is the JavaFX class to represent a window. So you don't need it here. Instead, you add the components that you want to use to the JFXPanel. See also here (function initAndShowGUI) how to do it.
In the init function of the example, a Scene is created as well as the chart itself. What you have to do to let the chart be shown is not much more than that - create a Scene, fill it with content and pass it to the JFXPanel that you already created.
With a minimum effort you can make your chart example run: Make sure that AdvancedLineChartSample.java is in your build path and that the function createChart is somehow accessible from your JFrame. Then add the chart to your code with something similar to the following snippet.
Group root=new Group();
Scene scene=new Scene(root);
myJFXPanel.setScene(scene);
root.getChildren().add(createChart());
This is just a very quick and dirty solution to run your example without any beautiful code and also I didn't test it. But hopefully it gives you a basic understanding of what's going on to encourage further experiments. By my own experience I can tell you that from this step on, there's a lot of fun to come with JavaFX 2.

Resources