I have a treetable column, to which I am adding checkbox as below
isPrimary.setCellFactory(new Callback<TreeTableColumn<String, Boolean>, TreeTableCell<String, Boolean>>() {
#Override
public TreeTableCell<String, Boolean> call(TreeTableColumn<String, Boolean> param) {
return new LiveCheckBoxTreeTableCell();
}
});
I am writing my own checkbox as below
public class LiveCheckBoxTreeTableCell extends TreeTableCell<String,Boolean>{
private final CheckBox checkBox = new CheckBox();
private ObservableList<CheckBox> selectedCheckBoxes = FXCollections.observableArrayList();
private ObservableList<CheckBox> unselectedCheckBoxes = FXCollections.observableArrayList();
#Override
public void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else{
setGraphic(checkBox);
if (checkBox.isSelected()) {
selectedCheckBoxes.add(checkBox);
} else {
unselectedCheckBoxes.add(checkBox);
}
checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean aBoolean, Boolean aBoolean2) {
if (aBoolean2) {
unselectedCheckBoxes.remove(checkBox);
selectedCheckBoxes.add(checkBox);
} else {
selectedCheckBoxes.remove(checkBox);
unselectedCheckBoxes.add(checkBox);
}
}
});
}
}
}
When I check one checkbox other checkbox in the isPrimary column should be disabled.
But the Checkbox I check and uncheck will get disabled. Others will remain enabled.
Any Javafx please help me to disable unchecked checkbox and enable all checkbox when I uncheck any checked checkbox.
Related
I have a RecyclerView list of CardViews and am using AppCompatActivity. Each CardView has a checkbox. When I click on the checkbox I would like to start a Contextual Action Bar. I would like to use an OnCheckedChangeListener and am having no luck. The checkmark correctly becomes visible when the "chkSelected" Checkbox is clicked on and it becomes invisible when the "chkSelected is clicked on again. What am I missing here?
public class MyRecylerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
...
private static ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
};
...
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
final ItemHolder itemHolder = new ItemHolder(view);
return itemHolder;
}
private static class ItemHolder extends RecyclerView.ViewHolder {
private CheckBox chkSelected;
private ItemHolder(View itemView) {
super(itemView);
chkSelected = (CheckBox) itemView.findViewById(R.id.chkSelected);
chkSelected.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
mActionMode = ((AppCompatActivity) buttonView.getContext()).startSupportActionMode(actionModeCallback);
}
});
}
I also tried an OnClickListener() in the ItemHolder() with no luck. Code is below. The Toast in the onClick() is showing properly so there must be something wrong with the startSupportActionMode().
chkSelected.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(),"Checkbox was clicked",Toast.LENGTH_LONG).show();
if(mActionMode == null) {
// Start the Contextual Action Bar (CAB) using the ActionMode.Callback defined above
mActionMode = ((AppCompatActivity) view.getContext()).startSupportActionMode(mActionModeCallback);
}
}
});
Solution was to set up a method in onBindViewHolder() that would update the item views for the OnClickListeners in Itemholder().
I want to create the following functionality for the serieses of a line chart when the user clicks on a checkbox on a table view. The table view for items has the ObservableList of the serieses of the chart. So the following code in the controller.
The controller class injects the following from the fxml file.
#FXML
public TableView<Series<Number, Number>> tableViewStatisticsOverview;
#FXML
public TableColumn<Series<Number, Number>, String> tableColumnStatisticName;
#FXML
public TableColumn<Series<Number, Number>, Series<Number, Number>> tableColumnShowSeries;
#FXML
public TableColumn<Series<Number, Number>, Series<Number, Number>> tableColumnAction;
//later on the code
tableViewStatisticsOverview.setItems(chart.getData()); // chart is a linexy chart
//setting up the tableColumnShowSeries to show a checkbox and show and hide the series
tableColumnShowSeries.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<Series<Number, Number>, Series<Number, Number>>, ObservableValue<Series<Number, Number>>>() {
#Override
public ObservableValue<Series<Number, Number>> call(CellDataFeatures<Series<Number, Number>, Series<Number, Number>> param) {
return new ReadOnlyObjectWrapper<Series<Number, Number>>(param
.getValue());
}
});
tableColumnShowSeries.setCellFactory(
new TableCollumnCellWithCheckBoxFactoryWrapper());
As data of the table I set the whole series on the row of the table so to be able to set the node of the series visible or not according to the value of the checkbox
TableCollumnCellWithCheckBoxFactoryWrapper class
package com.nokia.avalanche.client.util.fxhelper;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.util.Callback;
public class TableCollumnCellWithCheckBoxFactoryWrapper implements
Callback<TableColumn<Series<Number, Number>, Series<Number, Number>>, TableCell<Series<Number, Number>, Series<Number, Number>>> {
#Override
public TableCell<Series<Number, Number>, Series<Number, Number>> call(TableColumn<Series<Number, Number>, Series<Number, Number>> param) {
return new CheckBoxCell();
}
}
CheckBoxCell class
public class CheckBoxCell
extends TableCell<Series<Number, Number>, Series<Number, Number>> {
Logger LOG = LogManager.getLogger(CheckBoxCell.class);
private HBox checkBoxContainer;
private CheckBox checkBoxShow;
public CheckBoxCell() {
checkBoxContainer = new HBox();
checkBoxShow = new CheckBox("");
checkBoxContainer.setAlignment(Pos.CENTER);
checkBoxShow.setSelected(true);
checkBoxContainer.getChildren().add(checkBoxShow);
}
private void addListenerOnCheckBox(Series<Number, Number> series) {
checkBoxShow.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
LOG.debug("Show checkbox selected: "
+ checkBoxShow.isSelected());
series.getNode().setVisible(checkBoxShow.isSelected());
if (series.getNode().isVisible()) {
series.getNode().toFront();
for (Data<Number, Number> data : series.getData()) {
data.getNode().toFront();
}
} else {
series.getNode().toBack();
for (Data<Number, Number> data : series.getData()) {
data.getNode().toBack();
}
}
}
});
}
#Override
protected void updateItem(Series<Number, Number> series, boolean empty) {
super.updateItem(series, empty);
if (!empty && series != null) {
addListenerOnCheckBox(series);
LOG.debug("Series is not empty");
LOG.debug("Updating item for series with name: " + series.getName());
setGraphic(checkBoxContainer);
} else {
LOG.debug("Series is empty");
setGraphic(null);
}
}
}
The problem is that after adding some series on the chart and they show on the table and try to click on the check box one more check box behaves the same way as the one I am clicking that is It changes it's status from checked to unchecked according to the first one I click. Debugging shows that when code enters the handle method from the action handler the check box is the same object thus unchecking the one makes the other one unchecked. Have I missed something? Is there another way to use the check box and catch the change of checkbox status?
Two things I can see:
You should set up the listener on the check box once, from the
constructor. Use getItem() to get the current series being
displayed by the cell.
In updateItem you need to update the check box to match the state of whether that series is displayed.
So I think:
public class CheckBoxCell
extends TableCell<Series<Number, Number>, Series<Number, Number>> {
Logger LOG = LogManager.getLogger(CheckBoxCell.class);
private HBox checkBoxContainer;
private CheckBox checkBoxShow;
public CheckBoxCell() {
checkBoxContainer = new HBox();
checkBoxShow = new CheckBox("");
checkBoxContainer.setAlignment(Pos.CENTER);
checkBoxShow.setSelected(true);
checkBoxContainer.getChildren().add(checkBoxShow);
addListenerOnCheckBox();
}
private void addListenerOnCheckBox() {
checkBoxShow.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
Series<Number, Number> series = getItem();
if (series == null) {
return ;
}
LOG.debug("Show checkbox selected: "
+ checkBoxShow.isSelected());
series.getNode().setVisible(checkBoxShow.isSelected());
if (series.getNode().isVisible()) {
series.getNode().toFront();
for (Data<Number, Number> data : series.getData()) {
data.getNode().toFront();
}
} else {
series.getNode().toBack();
for (Data<Number, Number> data : series.getData()) {
data.getNode().toBack();
}
}
}
});
}
#Override
protected void updateItem(Series<Number, Number> series, boolean empty) {
super.updateItem(series, empty);
if (!empty && series != null) {
checkBoxShow.setSelected(series.getNode().isVisible());
LOG.debug("Series is not empty");
LOG.debug("Updating item for series with name: " + series.getName());
setGraphic(checkBoxContainer);
} else {
LOG.debug("Series is empty");
setGraphic(null);
}
}
}
Not tested, so there may be other things I have missed...
I have 1 issue in my project.
I'd like to have a tableColum built with comboBox, and for this i use:
tableColumn.setCellFactory(ComboBoxTableCell.forTableColumn(cbValues));
it works but like DOC says:
By default, the ComboBoxTableCell is rendered as a Label when not being edited, and as a ComboBox when in editing mode.
but i want to see the comboBox every time, so i build this code
tableColumn.setCellFactory(new Callback<TableColumn<Ambientale, Integer>, TableCell<Ambientale, Integer>>() {
#Override
public TableCell<Ambientale, Integer> call(TableColumn<Ambientale, Integer> param) {
return new ComboBoxCell(cbValues);
}
});
and my ComboBoxCell is:
class ComboBoxCell extends TableCell<Ambientale, Integer> implements Callback<Object, Object>{
private ComboBox combo;
public ComboBoxCell() {
combo = new ComboBox();
}
public ComboBoxCell(ObservableList items) {
combo = new ComboBox();
combo.setItems(items);
combo.setOnAction(new EventHandler() {
#Override
public void handle(Event event) {
System.out.println(" it's works");
commitEdit((Integer)combo.getSelectionModel().getSelectedItem());
}
});
}
#Override
public void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
combo.getSelectionModel().select(item);
setGraphic(combo);
setContentDisplay(ContentDisplay.CENTER);
}
}
#Override
public Object call(Object param) {
return new ComboBoxCell();
}
}
the issue is here!
class ComboBoxCell extends TableCell<Ambientale, Integer> implements Callback<Object, Object>{
private ComboBox combo;
public ComboBoxCell() {
combo = new ComboBox();
}
public ComboBoxCell(ObservableList items) {
combo = new ComboBox();
combo.setItems(items);
combo.setOnAction(new EventHandler() {
#Override
public void handle(Event event) {
System.out.println(" it's works");
commitEdit((Integer)combo.getSelectionModel().getSelectedItem());
}
});
}
#Override
public void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
combo.getSelectionModel().select(item);
setGraphic(combo);
setContentDisplay(ContentDisplay.CENTER);
}
}
#Override
public Object call(Object param) {
return new ComboBoxCell();
}
}
commitEdit(...) doesn't call:
tableColumn.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Ambientale, Integer>>() {
#Override
public void handle(TableColumn.CellEditEvent<Ambientale, Integer> t) { //aggiornare database cella singola
System.out.println("not called");
//other stuffs
}
});
Can you help me please.
It works, i don't know why but it works.
i've added this on my ComboBoxCell
combo.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (newValue) {
getTableView().edit(getIndex(), getTableColumn());
} else {
commitEdit((Integer)combo.getSelectionModel().getSelectedItem());
}
}
});
i need help to get a specified list of items from ObservableList and add them to a combo box.
My ObservableList contains value received from DB (in specific a table with just 3 columns) and i want to show only one column value in combo box. When combo box is selected the other values are charged in 2 textfield.
Code as follows.
ImportAccettazioniModel:
public ObservableList<Impostazioni> listImpostazioni = FXCollections.observableArrayList();
public static class Impostazioni {
private final StringProperty rowid;
private final StringProperty nome;
private final StringProperty operatore;
private final StringProperty delimitatore;
private Impostazioni(String Rowid, String Nome, String Operatore, String Delimitatore) {
this.rowid = new SimpleStringProperty(Rowid);
this.nome = new SimpleStringProperty(Nome);
this.operatore = new SimpleStringProperty(Operatore);
this.delimitatore = new SimpleStringProperty(Delimitatore);
}
public StringProperty rowidProperty() { return rowid; }
public StringProperty nomeProperty() { return nome; }
public StringProperty operatoreProperty() { return operatore; }
public StringProperty delimitatoreProperty() { return delimitatore; }
}
ImportAccettazioniController:
#FXML
private ComboBox<ImportAccettazioniModel.Impostazioni> comboCaricaNome;
// get data from model to popupate combobox
public final void getImpostazioniDataFields() {
comboCaricaNome.getItems().clear();
comboCaricaNome.setItems(model.listImpostazioni);
comboCaricaNome.setCellFactory(new Callback<ListView<Impostazioni>, ListCell<Impostazioni>>() {
#Override public ListCell<Impostazioni> call(ListView<Impostazioni> p) {
return new ListCell<Impostazioni>() {
#Override
protected void updateItem(Impostazioni t, boolean bln) {
super.updateItem(t, bln);
if(t != null){
setText(t.nomeProperty().toString().toUpperCase());
System.out.println("SET PROPERTY " + t.nomeProperty().toString());
} else {
setText(null);
}
}
};
}
});
}
comboCaricaNome.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<ImportAccettazioniModel.Impostazioni>() {
#Override public void changed(ObservableValue<? extends ImportAccettazioniModel.Impostazioni> observable,ImportAccettazioniModel.Impostazioni oldValue, ImportAccettazioniModel.Impostazioni newValue) {
setTextFields(newValue);
}
});
//set data to textfield with the selected combo box
private void setTextFields(Impostazioni listImpostazioni) {
//setRowid(Impostazioni.rowidProperty().getValue());
if (comboCaricaNome.getItems().isEmpty()) {
editCaricaOperatore.setText("");
editCaricaDelimitatore.setText("");
} else {
editCaricaOperatore.setText(listImpostazioni.operatoreProperty().getValue());
editCaricaDelimitatore.setText(listImpostazioni.delimitatoreProperty().getValue());
}
}
Now, the logic seems to work but my combo box doesn't contain the value nomeProperty().
How can i solve?
Thanks in advance
To get the observed value of the JavaFX Property use Property.get() or Property.getValue().
By convention, the Java developers override toString() method to not show message for customers, instead it is used for internal usages by another developers.
As a result, the line
setText(t.nomeProperty().toString().toUpperCase());
should be
setText(t.nomeProperty().getValue().toUpperCase());
UPDATE:
Since you are using the ComboBox rather than ChoiceBox, you should also override default button cell property of combobox, according to your needs:
comboCaricaNome.setButtonCell(new ListCell<Impostazioni>() {
#Override
protected void updateItem(Impostazioni t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
setText(t.nomeProperty().getValue().toUpperCase());
} else {
setText(null);
}
}
});
As you can see this is the same ListCell which is set for cellFactory. Refactoring is up to you, or of course you can implement a listcell with different content as well.
I have a combobox which shows list of User objects. I have coded a custom cell factory for the combobox:
#FXML ComboBox<User> cmbUserIds;
cmbUserIds.setCellFactory(new Callback<ListView<User>,ListCell<User>>(){
#Override
public ListCell<User> call(ListView<User> l){
return new ListCell<User>(){
#Override
protected void updateItem(Useritem, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getId()+" "+item.getName());
}
}
} ;
}
});
ListView is showing a string(id+name), but when I select an item from listview, Combobox is showing toString() method return value i.e address of object.
I can't override toString() method, because the User domain object should be same as the one at server.
How to display id in combobox? Please suggest
EDIT1
I tried below code. Now combo box shows id when I select a value from the listview.
cmbUserIds.setConverter(new StringConverter<User>() {
#Override
public String toString(User user) {
if (user== null){
return null;
} else {
return user.getId();
}
}
#Override
public User fromString(String id) {
return null;
}
});
The selected value in combo box is cleared when control focus is lost. How to fix this?
EDIT2:
#FXML AnchorPane root;
#FXML ComboBox<UserDTO> cmbUsers;
List<UserDTO> users;
public class GateInController implements Initializable {
#Override
public void initialize(URL location, ResourceBundle resources) {
users = UserService.getListOfUsers();
cmbUsers.setItems(FXCollections.observableList(users));
cmbUsers.getSelectionModel().selectFirst();
// list of values showed in combo box drop down
cmbUsers.setCellFactory(new Callback<ListView<UserDTO>,ListCell<UserDTO>>(){
#Override
public ListCell<UserDTO> call(ListView<UserDTO> l){
return new ListCell<UserDTO>(){
#Override
protected void updateItem(UserDTO item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getUserId()+" "+item.getUserNm());
}
}
} ;
}
});
//selected value showed in combo box
cmbUsers.setConverter(new StringConverter<UserDTO>() {
#Override
public String toString(UserDTO user) {
if (user == null){
return null;
} else {
return user.getUserId();
}
}
#Override
public UserDTO fromString(String userId) {
return null;
}
});
}
}
Just create and set a CallBack like follows:
#FXML ComboBox<User> cmbUserIds;
Callback<ListView<User>, ListCell<User>> cellFactory = new Callback<ListView<User>, ListCell<User>>() {
#Override
public ListCell<User> call(ListView<User> l) {
return new ListCell<User>() {
#Override
protected void updateItem(User item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
setText(item.getId() + " " + item.getName());
}
}
} ;
}
}
// Just set the button cell here:
cmbUserIds.setButtonCell(cellFactory.call(null));
cmbUserIds.setCellFactory(cellFactory);
You need to provide a functional fromString() Method within the Converter!
I had the same problem as you have and as I implemented the fromString() with working code, the ComboBox behaves as expected.
This class provides a few of my objects, for dev-test purposes:
public class DevCatProvider {
public static final CategoryObject c1;
public static final CategoryObject c2;
public static final CategoryObject c3;
static {
// Init objects
}
public static CategoryObject getCatForName(final String name) {
switch (name) {
case "Kategorie 1":
return c1;
case "Cat 2":
return c2;
case "Steuer":
return c3;
default:
return c1;
}
}
}
The converter object:
public class CategoryChooserConverter<T> extends StringConverter<CategoryObject> {
#Override
public CategoryObject fromString(final String catName) {
//This is the important code!
return Dev_CatProvider.getCatForName(catName);
}
#Override
public String toString(final CategoryObject categoryObject) {
if (categoryObject == null) {
return null;
}
return categoryObject.getName();
}
}