I'm trying to bind the textProperty of the Label to the object's SimpleIntegerProperty with help of Bindings but it does not change the text when I change the SimpleIntegerProperty of the object in real time. Any help would be appreciated of how to make textProperty change.
package sample;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable
{
#FXML
private Slider slider;
#FXML
private Label label;
#Override
public void initialize(URL location, ResourceBundle resources) {
MyObject object = new MyObject(0);
label.textProperty().bind(Bindings.createStringBinding(() -> " hello " + object.numberProperty().get() * (10 + 12)/2));
object.numberProperty().bind(slider.valueProperty());
}
}
class MyObject {
private SimpleIntegerProperty number;
public Object(int number){
this.number = new SimpleIntegerProperty(number);
}
public SimpleIntegerProperty numberProperty(){return this.number;}
}
You need to "tell" Bindings, which Observables to observe for changes. This varargs parameter is the second parameter of the createStringBinding method. In this case you need to pass only a single Observable: object.numberProperty()
label.textProperty().bind(
Bindings.createStringBinding(
() -> " hello " + object.numberProperty().get() * (10 + 12)/2,
object.numberProperty()));
Related
I want to test, if a certain TextField (maybe there are several TextFields) has an EventHandler set via setOnAction. In the test code I can set the content (e.g. "HelloWorld") into the TextField. In my understanding I have to place the curser at the end of the text in the TextField and then, call press(KeyCode.ENTER). Is there a TestFX call to place the curser a a certain point within a certain TextField? Or is there another way to test this?
Regards, Jörg
[EDIT]
Here is an example:
package testestfx;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
public class SimpleGui extends VBox {
private static final org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger(SimpleGui.class);
private TextField field1;
private TextField field2;
private Label label;
public SimpleGui() {
field1 = new TextField("Textfield1");
field2 = new TextField("Textfield2");
field1.setOnAction((event) -> onActionDoThis());
field2.setOnAction((event) -> onActionDoThat());
label = new Label("Label");
getChildren().addAll(field1, field2 );
}
public TextField getField1() {
return field1;
}
public TextField getField2() {
return field2;
}
public Label getLabel() {
return label;
}
void onActionDoThis() {
logger.info("This");
label.setText("This");
}
void onActionDoThat() {
logger.info("That");
label.setText("That");
}
}
And here is the test:
package testtestfx;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.stage.Stage;
import org.junit.Test;
import org.testfx.framework.junit.ApplicationTest;
import testestfx.SimpleGui;
import static org.junit.Assert.assertEquals;
public class TestSimpleGUI extends ApplicationTest {
private static final org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger(TestSimpleGUI.class);
private SimpleGui gui;
#Override
public void start(final Stage stage) throws Exception {
super.start(stage);
gui = new SimpleGui();
stage.setScene(new Scene(gui));
stage.show();
}
#Test
public void testEnterKeystroke() {
TextField t2 = gui.getField2();
TextField t1 = gui.getField1();
Label l1 = gui.getLabel();
t2.setText("bar");
t1.setText("foo");
press(KeyCode.ENTER);
assertEquals("That", l1.getText());
}
}
The console output is:
15:43:29.366 [JavaFX Application Thread] [INFO] SimpleGui - This
org.junit.ComparisonFailure:
Expected :That
Actual :This
```
You can set the focus on a TextField like this:
myTextField.requestFocus();
kind regards
Amadeus
I hope you can help me. I'm trying to round a image retrieved from my database. In the next image you can see the image is correctly displayed in a imageview. User selects a new item in the table and the image change to display the correct image, this is working, no problems here.
This is the program
I try with this code in the gestionarEventos :
imgfotovisi.imageProperty().bind(imageRetrievalService.valueProperty());
Image im = imgfotovisi.getImage();
circulo.setFill(new ImagePattern(im));
But java say :
... 58 more
Caused by: java.lang.NullPointerException: Image must be non-null.
at javafx.scene.paint.ImagePattern.<init>(ImagePattern.java:235)
The program runs if I delete the lines below the
imgfotovisi.imageProperty().bind(imageRetrievalService.valueProperty());
line.
When it runs, I don't know why says the image is null, when I can see clearly there.
This is ver_visitantes class:
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ResourceBundle;
import java.util.function.Predicate;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.InputEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.ImagePattern;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class ver_visitantes implements Initializable {
#FXML private TableView<visitantes> tbvisitantes;
#FXML private TableColumn<visitantes, String> clcedula,clnombres,clapellidos,clapartamento,clcelular,clobservaciones;
#FXML private ImageView imgfotovisiact,imgfotoact,imgfotovisi,imgfoto;
#FXML private TextField txtcedula,txtnombres,txtapto,txtapellidos,txtapt,txtcelular,txtobservaciones;
#FXML private Label lblinfovisiact,lblusuario,lblstatusvisi;
#FXML private Circle circulo;
private ObservableList<visitantes> visitorlist;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
ConexionSQL cnt = new ConexionSQL();
cnt.conexion();
visitorlist = FXCollections.observableArrayList();
visitantes.llenarlistavisitas(cnt.conexion(), visitorlist);
tbvisitantes.setItems(visitorlist);// llenar table view con la lista
clcedula.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getcedula()));
clnombres.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getnombres()));
clapellidos.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getapellidos()));
clapartamento.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getapartamento()));
clcelular.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getcelular()));
clobservaciones.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getobservaciones()));
gestionarEventos();
tbvisitantes.getSelectionModel().selectFirst();
}
public void gestionarEventos() {
tbvisitantes.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<visitantes>() {
#Override
public void changed(ObservableValue<? extends visitantes> arg0, visitantes valorAnterior,
visitantes valorSeleccionado) {
imgfoto.setVisible(false);
btnmodificar.setDisable(false);
btncancelar.setDisable(false);
btneliminar.setDisable(false);
imageRetrievalService.restart();
if (valorSeleccionado != null) {
txtcedula.setText(String.valueOf(valorSeleccionado.getcedula()));
txtnombres.setText(valorSeleccionado.getnombres());
txtapellidos.setText(valorSeleccionado.getapellidos());
txtapto.setText(String.valueOf(valorSeleccionado.getapartamento()));
txtcelular.setText(String.valueOf(valorSeleccionado.getcelular()));
txtobservaciones.setText(String.valueOf(valorSeleccionado.getobservaciones()));
}
}
});
imgfotovisi.imageProperty().bind(imageRetrievalService.valueProperty());
}
private final Service<Image> imageRetrievalService = new Service<Image>() {// cargar imagen en visitantes
#Override
protected Task<Image> createTask() {
final String id;
final visitantes visitante = tbvisitantes.getSelectionModel().getSelectedItem();
if (visitante == null) {
id = null;
} else {
id = visitante.getcedula();
}
return new Task<Image>() {
#Override
protected Image call() throws Exception {
if (id == null) {
return null;
}
return visitante.getImageById(id);
}
};
}
};
}
this is the visitantes class,called from the imageRetrievalService to get the image:
package application;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.scene.image.Image;
public class visitantes {
private StringProperty cedula;
private StringProperty nombres;
private StringProperty apellidos;
private StringProperty apartamento;
private StringProperty celular;
private StringProperty observaciones;
public visitantes(String cedula,String nombres,String apellidos,String apartamento,String celular,String observaciones){
this.cedula = new SimpleStringProperty(cedula);
this.nombres = new SimpleStringProperty(nombres);
this.apellidos = new SimpleStringProperty(apellidos);
this.apartamento = new SimpleStringProperty(apartamento);
this.celular = new SimpleStringProperty(celular);
this.observaciones = new SimpleStringProperty(observaciones);
}
public String getnombres(){
return nombres.get();
}
public void setnombres(String nombres){
this.nombres = new SimpleStringProperty(nombres);
}
public String getcedula(){
return cedula.get();
}
public void setcedula(String cedula){
this.cedula = new SimpleStringProperty(cedula);
}
public String getapellidos(){
return apellidos.get();
}
public void setapellidos(String apellidos){
this.apellidos = new SimpleStringProperty(apellidos);
}
public String getapartamento(){
return apartamento.get();
}
public void setapartamento(String apartamento){
this.apartamento = new SimpleStringProperty(apartamento);
}
public String getcelular(){
return celular.get();
}
public void setcelular(String celular){
this.celular = new SimpleStringProperty(celular);
}
public Image getImageById(String id) throws SQLException, IOException {
try (
ConexionSQL cn = new ConexionSQL();
Connection con = cn.conexion();
PreparedStatement ps = con.prepareStatement(
"SELECT foto_visi FROM visitantes WHERE cedula_visi = ?");
) {
ps.setString(1, id);
ResultSet results = ps.executeQuery();
Image img = null ;
if (results.next()) {
Blob foto = results.getBlob("foto_visi");
InputStream is = foto.getBinaryStream();
img = new Image(is) ; // false = no background loading
is.close();
}
results.close();
return img ;
} catch (Throwable e) {
String info = e.getMessage();
System.out.println(info);
}
return null;
}
}
I think the problem is here:
imgfotovisi.imageProperty().bind(imageRetrievalService.valueProperty());
I don't know if the retrieved image is loaded in the imageivew in this line. Looks like yes, but if I do
Image im = imgfotovisi.getImage();
Java says it is null. Then I can't get the image into the circle.
Thanks in advance :)
bind isn't going to load an image itself, it will just bind so that one variable will change when the source changes (in this case the value property of the service), which isn't going to happen straight away as the service is running asynchronously. So, if you query the value straight away after issuing the bind statement, you won't get the result you are expecting, as the source hasn't yet changed.
Instead you need to take action only once the image is actually available.
For instance:
imageRetrievalService.valueProperty().addListener((obs, oldVal, newVal) ->
if (newVal != null)
circulo.setFill(new ImagePattern(newVal))
);
Or, if you don't want a direct linkage to the service, and given that the imgfotovsi image property is already bound to the service value:
imgfotovisi.imageProperty().addListener((obs, oldVal, newVal) ->
if (newVal != null)
circulo.setFill(new ImagePattern(newVal))
);
I created a book management application via javafx. Through this app we can perform add, search and delete operations. For the search i am using Table view to get all the details of the book searched by the user. So in the end i am getting the result displayed in the console but not in the table view
package Managemnet;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import connection.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
public class Searching {
Connection connect;
#FXML
TableView<Book> search_view ;
#FXML
ObservableList<Book> observeList;
#FXML
TableColumn<Book, Integer> Book_I;
#FXML
TableColumn<Book, String> Book_n;
#FXML
TableColumn<Book, String> publish;
#FXML
TableColumn<Book, Integer> ye;
#FXML
TextField sea_Book_name;
#FXML
TextField sea_pub;
#FXML
TextField sea_year;
#FXML
AnchorPane SearchPane;
#FXML
Button search;
public void search() throws ClassNotFoundException, SQLException{
Sql_query sql = new Sql_query();
sql.connect_sql();
connect = sql.getConnect();
observeList = FXCollections.<Book>observableArrayList();
search_view = new TableView<Book>();
Book_I=new TableColumn<Book ,Integer>();
Book_I.setCellValueFactory(new PropertyValueFactory<Book ,Integer>
("Book_id"));
Book_n=new TableColumn<Book ,String>();
Book_n.setCellValueFactory(new PropertyValueFactory<Book ,String>
("Book_name"));
publish=new TableColumn<Book ,String>();
publish.setCellValueFactory(new PropertyValueFactory<Book ,String>
("Publisher"));
ye=new TableColumn<Book ,Integer>();
ye.setCellValueFactory(new PropertyValueFactory<Book ,Integer>("year"));
String s1= sea_Book_name.getText();
String s2= sea_pub.getText();
String s= sea_year.getText();
int s3;
if(!s.isEmpty()){
s3=Integer.parseInt(s);
}
else s3=0;
ResultSet res;
Answer_from_dataset obj= new Answer_from_dataset();
res=obj.getAnswer(s1, s2, s3);
while(res.next()){
observeList.add(new Book(res.getInt(1), res.getString(2),
res.getString(3), res.getInt(4)));
//System.out.println(observeList);
}
search_view.setItems(observeList);
System.out.println(search_view);
}
package Managemnet;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
public class Book {
SimpleStringProperty Book_name;
SimpleStringProperty Publisher;
SimpleIntegerProperty Book_id;
SimpleIntegerProperty year;
public Book(int book_id, String book_name, String publisher, int year) {
this.Book_name =new SimpleStringProperty(book_name);
this.Publisher =new SimpleStringProperty(publisher);
this.Book_id =new SimpleIntegerProperty (book_id);
this.year = new SimpleIntegerProperty(year);
}
public String getBook_name() {
return Book_name.get();
}
public String getPublisher() {
return Publisher.get();
}
public Integer getBook_id() {
return Book_id.get();
}
public Integer getYear() {
return year.get();
}
public void setBook_name(String book_name) {
Book_name.set(book_name);
}
public void setPublisher(String publisher) {
Publisher.set(publisher);;
}
public void setBook_id(int book_id) {
Book_id.set(book_id);;
}
public void setYear(int year) {
this.year.set(year);;
}
#Override
public String toString() {
return getBook_id() + " " + getBook_name() + " " + getPublisher() + " "
+ getYear();
}
}
So I ran into this issue with FXML when I did my first project with JavaFX.
I tried a lot of solutions with FXML but it took time and nothing worked. So I shifted over to using POJO's. This may not be ideally what you're looking for but it would give you a pretty good amount of flexibility with creating your table.
Ideally for the table itself you want to create a TableView
TableView<Book> table = new TableView();
Then for each column you want to create a TableColumn.. Now here you need to be careful
TableColumn<Book, String> col1 = new TableColumn<>("Name");
col.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().getName()));
The values within the angle brackets is <Object Type, Data Type>
And then of course you can set your preferred width and what not. But the same process of creating TableColumns Repeats itself for the table you have. I get this might be a little more of lengthier process but its relatively easy to understand and most importantly it work.
Try this and let me know if it works! Cheers!!
I am begging with JavaFx, and I realized that I need some help to update a TreeView with some TreeItems in runtime, and it should be updated in the main window.
Here, you can see a screenshot of the two windows:
The bigger is the main window and it calls (by clicking in File >> New Project), new smaller. In the smaller window, I could get the String that is typed and than the enter button is clicked.
The trouble is: How can I show the new items created by the "new project window" (the smaller window in the pic) in the TreeView in the main window(the bigger)?
The treeview is in the left side of the main window.
I hope I was clear.
Here is the code of the controllers of these windows:
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeItem.TreeModificationEvent;
import javafx.scene.control.TreeView;
import javafx.stage.Modality;
import javafx.stage.Stage;
/**
* this class handles with the main window of our LDF Tool
* #author Vinicius
* #version 1.0
*/
public class MainController implements Initializable{
#FXML
TreeView<String> treeView;
#FXML
MenuItem newProject;
private boolean flag = false;
private NewProjectWindowController npwc;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML
public void newProjectClicked(ActionEvent event){
try{
flag = true;
FXMLLoader fxml = new FXMLLoader(getClass().getResource("newProjectWindow.fxml"));
Parent root = (Parent) fxml.load();
Stage newWindow = new Stage();
newWindow.setTitle("New Project");
newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setScene(new Scene(root));
newWindow.show();
} catch (Exception e) {
System.out.println("caiu na exceção");
}
}
/**
* to this method, choose the project's name as argument, and it will be put on the
* tree with the archives that should be created together
* #param projectName
*/
public void doTree(String projectName){
TreeItem<String> root = new TreeItem<>("projectName");
root.setExpanded(true);
//TreeItem<String> folha1 = new TreeItem<String>(projectName + " arquivo 1");
//root.getChildren().add(folha1);
treeView.setRoot(root);
}
The other controller class:
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class NewProjectWindowController implements Initializable{
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#FXML
Button cancelButton;
#FXML
Button enterButton;
#FXML
TextField textInput;
private String input;
public String getInput(){
return this.input;
}
#FXML
public void cancelButtonClicked(ActionEvent event) {
Stage window = (Stage) this.cancelButton.getParent().getScene().getWindow();
window.close();
}
#FXML
public void enterButtonClicked(ActionEvent event) {
input = hasString();
Stage window = (Stage) this.enterButton.getParent().getScene().getWindow();
window.close();
}
private String hasString(){
if (this.textInput.getText().isEmpty())
return null;
return this.textInput.getText();
}
}
Please, assume that I mapped everything ok in the FXML file.
thanks
#FXML
public void newProjectClicked(ActionEvent event){
try{
flag = true;
FXMLLoader fxml = new FXMLLoader(getClass().getResource("newProjectWindow.fxml"));
Parent root = (Parent) fxml.load();
Stage newWindow = new Stage();
newWindow.setTitle("New Project");
newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setScene(new Scene(root));
// showAndWait blocks execution until the window closes:
newWindow.showAndWait();
NewProjectWindowController controller = fxml.getController();
String input = controller.getInput();
if (input != null) {
TreeItem<String> currentItem = treeView.getSelectionModel().getSelectedItem();
if (currentItem == null) currentItem = treeView.getRoot();
currentItem.getChildren().add(new TreeItem<>(input));
}
} catch (Exception e) {
System.out.println("caiu na exceção");
}
}
The code below contains two Listview's, the user is to select a name from the first list view and when the add button is hit, it will move the content to an array which the 2nd List view is supposed to update and display as changes are made.
I thought we had the correct idea by converting the selection to a string then adding it to array. But when attempting to print the array for test purposes nothing appears.
any feed back or help would be greatly appreciated
package poolproject;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
/**
*
* #author Alex
*/
public class FXMLDocumentController implements Initializable {
#FXML
private Button BtnAdd;
#FXML
private ListView<String> boxTeam;
#FXML
private ListView<String> boxPlayers;
ArrayList<String> team= new ArrayList();
String player;
final ObservableList<String> playersAvailable = FXCollections.observableArrayList(
"Kardi","Gilmore","Clark");
final ObservableList<String> teamOutput = FXCollections.observableArrayList(team);
#FXML
private void deleteAction(ActionEvent action){
int selectedItem = boxPlayers.getSelectionModel().getSelectedIndex();
player = Integer.toString(selectedItem);
team.add(player);
playersAvailable.remove(selectedItem);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
boxPlayers.setItems(playersAvailable);
boxTeam.setItems(teamOutput);
}
}
Adding an item to a plain list will not cause updates to be fired (the ArrayList does not have a mechanism to register any listeners). Adding an item to an ObservableList will cause listeners to be notified.
Do
String selectedItem = boxPlayers.getSelectionModel().getSelectedItem();
playersAvailable.remove(selectedItem);
teamOutput.add(selectedItem);