JavaFX: Add UI control to TreeTableView - java

Let's say i have 2 columns in a TreeTableView and now i want to add a string/Label in the first column and a ProgressBar in the other one. How would i accomplish something like this?
Really appreciate any help!

As correctly pointed out by James_D, you can use ProgressBarTreeTableCell for a column with ProgressBars. There is internal supports for some other UI controls such as TextField, CheckBox etc.
For other UI controls you can create a Custom TreeTableCell
as shown:
private class ProgressCell extends TreeTableCell<Employee, String> {
final ProgressBar progress = new ProgressBar();
ProgressCell() {
}
#Override
protected void updateItem(String t, boolean empty) {
super.updateItem(t, empty);
if (!empty) {
setGraphic(progress);
}
}
}
and then assign a CellFactory to the second column
secondCol.setCellFactory(
new Callback<TreeTableColumn<Employee, String>, TreeTableCell<Employee, String>>() {
#Override
public TreeTableCell<Employee, String> call(
TreeTableColumn<Employee, String> param) {
return new ProgressCell();
}
});
where Employee is the POJO class on which the TreeTableView is built

Related

Adding JFXButton into a JFXTreeTableView

I have tried to research about this, but could not find any examples. The examples I found were regarding normal TableView only. I could only create a JFXTreeTableView with an object and list out String. Any help would be appreciated! Thanks!
I need to put a button or basically any other object than a string into a TreeTableView.
Updated to make it clear on what I wanted it to look like, and the solution is below.
With reference to this post, I was trying to add a Button(Specifically JFXButton) into a TreeTableView(Specifically JFXTreeTableView)
How to add button in JavaFX table view
However, the post only talks about TableView. After analyzing the codes I tried to modify the codes to work with TreeTableView and TreeTableCell instead.
Using the sample codes from JFoenix and modifying it as seen in the codes snippets below, I could load a JFXButton into a JFXTreeTableView. (Also works with normal Button. Just replace the JFXButton to Button)
JFXTreeTableColumn<User, String> settingsColumn = new JFXTreeTableColumn<>("Others");
settingsColumn.setPrefWidth(100);
Callback<TreeTableColumn<User, String>, TreeTableCell<User, String>> cellFactory
= //
new Callback<TreeTableColumn<User, String>, TreeTableCell<User, String>>() {
#Override
public TreeTableCell call(final TreeTableColumn<User, String> param) {
final TreeTableCell<User, String> cell = new TreeTableCell<User, String>() {
final JFXButton btn = new JFXButton("Just Do it");
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
setText(null);
} else {
btn.setButtonType(JFXButton.ButtonType.RAISED);
btn.setOnAction(event -> {
//Button Action here
});
setGraphic(btn);
setText(null);
}
}
};
return cell;
}
};
settingsColumn.setCellFactory(cellFactory);
//Also remember to add the new column in
treeView.getColumns().setAll(deptColumn, ageColumn, empColumn, settingsColumn);
This is the end result:

How to update every cell in a TableView [JavaFX]

Is it possible to update every cell in a TableView with JavaFX? Actually, I get a new object in an ObservableList and, automatically, I also get a new row in the TableView.
But I also need to update the other rows. Is it possible? As far as I understand, the code below update just the first row in the table.
#Override
public TableCell<AtisMessage, String> call(TableColumn<AtisMessage, String> param) {
final TableCell<AtisMessage, String> cell = new TableCell<AtisMessage, String>() {
private TextFlow tf;
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty()) {
Text text = new Text(item.toString());
tf = new TextFlow(text);
tf.setPrefWidth(Control.USE_COMPUTED_SIZE);
tf.setMaxHeight(Control.USE_COMPUTED_SIZE);
setGraphic(tf);
}
}
};
cell.setPrefHeight(65);
return cell;
}

"Cannot find symbol constructor, EventHandler does not take parameters" when setting the action for a button in JavaFX

I am creating a program in JavaFX which lists tasks from a data base and displays a button for each row with allows a user to register the task as claimed in the database. I used the code on this link to help me with the buttons for each row: https://gist.github.com/jewelsea/3081826.
However, after changing the code to fit my program, i am getting an error in relation to setting the action of the cellButton variable. I have also added the class that calls this method, just in case.
CANNOT FIND SYMBOL CONSTRUCTOR, EVENTHANDLER DOES NOT TAKE PARAMETERS..
& METHOD DOES NOT OVERRIDE OR IMPLEMENT A METHOD FROM A SUPERTYPE (I am guessing this error is as a result of the first two errors).
//Define the button cell
private class ButtonCell extends TableCell<task, Boolean> {
final Button cellButton = new Button("Claim");
ButtonCell(){
//Action when the button is pressed
cellButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
// get Selected Item
task currentPerson = (task) ButtonCell.this.getTableView().getItems().get(ButtonCell.this.getIndex());
//remove selected item from the table list
newMan.claimTask(currentPerson.getTaskID());
}
});
}
//Display button if the row is not empty
#Override
protected void updateItem(Boolean t, boolean empty) {
super.updateItem(t, empty);
if(!empty){
setGraphic(cellButton);
}
}
}
x
private TableView createTasksTable() {
TableView tableView = new TableView();
TableColumn<task,String> firstNameCol = new TableColumn<>("Task");
firstNameCol.setCellValueFactory(new Callback<CellDataFeatures<task, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(CellDataFeatures<task, String> p) {
// p.getValue() returns the Person instance for a particular TableView row
return new SimpleStringProperty(p.getValue().getName());
}
});
//Insert Button
TableColumn col_action = new TableColumn<>("Action");
tableView.getColumns().add(col_action);
col_action.setCellValueFactory(
new Callback<TableColumn.CellDataFeatures<task, Boolean>,
ObservableValue<Boolean>>() {
#Override
public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<task, Boolean> p) {
return new SimpleBooleanProperty(p.getValue() != null);
}
});
//Adding the Button to the cell
col_action.setCellFactory(
new Callback<TableColumn<task, Boolean>, TableCell<task, Boolean>>() {
#Override
public TableCell<task, Boolean> call(TableColumn<task, Boolean> p) {
return new ButtonCell();
} });
tableView.getColumns().addAll(firstNameCol);
return tableView;
}
You have probably imported the wrong EventHandler. Make sure you have
import javafx.event.EventHandler ;
and not something from awt.

JavaFX TableColumn text wrapping

I am experiencing an issue when resizing a TableView which contains text items that wrap around TableCell items. Upon resizing, hidden values are resized but the visible items do not re-calculate the text wrapping.
The tweets in the red box were hidden during the resize and had their text wrapping adjusted as expected. Tweets above the box were visible during the resize phase and still have the old wrapping.
Below is my code for the resize phase.
fxSearchResultsTableTweet.setCellFactory(new Callback<TableColumn<Status, String>, TableCell<Status, String>>() {
#Override
public TableCell<Status, String> call(TableColumn<Status, String> arg0) {
return new TableCell<Status, String>() {
private Text text;
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty()) {
text = new Text(item.toString());
text.setWrappingWidth(fxSearchResultsTableTweet.getWidth());
this.setWrapText(true);
setGraphic(text);
}
}
};
}
});
}
Any help would be greatly appreciated.
This is closer, but not great:
textCol.setCellFactory(new Callback<TableColumn<Status, String>, TableCell<String, String>>() {
#Override
public TableCell<Status, String> call(
TableColumn<Status, String> param) {
TableCell<Status, String> cell = new TableCell<>();
Text text = new Text();
cell.setGraphic(text);
cell.setPrefHeight(Control.USE_COMPUTED_SIZE);
text.wrappingWidthProperty().bind(cell.widthProperty());
text.textProperty().bind(cell.itemProperty());
return cell ;
}
});
In 2.2 this displays the wrong height when you add new items to the table, then on resize the cells are sized correctly. In 8 it's almost perfect, just seems to fail after the first item is added (at least in my mock-up).
As noted in the comments,
textCol.setCellFactory(tc -> {
TableCell<Status, String> cell = new TableCell<>();
Text text = new Text();
cell.setGraphic(text);
cell.setPrefHeight(Control.USE_COMPUTED_SIZE);
text.wrappingWidthProperty().bind(textCol.widthProperty());
text.textProperty().bind(cell.itemProperty());
return cell ;
});
appears to work better.
Just add cell factory on each table of column.
It should add before adding your data to table view.
It is worked fine for me.
yourTableColumn.setCellFactory(param -> {
return new TableCell<YourDataClass, String>() {
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle("");
} else {
Text text = new Text(item);
text.setStyle("-fx-text-alignment:justify;");
text.wrappingWidthProperty().bind(getTableColumn().widthProperty().subtract(35));
setGraphic(text);
}
}
};
});

JavaFX tableview with colorpicker editor

I have a TableView that uses a ColorPicker to (display/edit) colors in a cell.
The table display the ColorPicker in the desired field, but edits aren't working.
TableColumn<SeriesPreferences, Color> c2 = new TableColumn<SeriesPreferences, Color>("Color");
c2.setCellValueFactory(new PropertyValueFactory<SeriesPreferences, Color>("color"));
c2.setCellFactory(new Callback<TableColumn<SeriesPreferences, Color>,
TableCell<SeriesPreferences, Color>>()
{
#Override
public TableCell<SeriesPreferences, Color>
call(final TableColumn<SeriesPreferences, Color> param)
{
TableCell<SeriesPreferences, Color> cell =
new TableCell<SeriesPreferences, Color>()
{
#Override
public void updateItem(Color c, boolean empty)
{
if(c != null)
{
final ColorPicker cp = new ColorPicker();
cp.setValue(c);
setGraphic(cp);
cp.setOnAction(new EventHandler<javafx.event.ActionEvent>()
{
public void
handle(javafx.event.ActionEvent t)
{
getTableView().edit(getTableRow().getIndex(), param);
commitEdit(cp.getValue());
}
});
}
}
};
return cell;
}
});
c2.setOnEditCommit(new EventHandler<CellEditEvent<SeriesPreferences, Color>>()
{
#Override
public void handle(CellEditEvent<SeriesPreferences, Color> t)
{
((SeriesPreferences) t.getTableView().getItems().get(t.getTablePosition().
getRow())).setColor(t.getNewValue());
}
});
The edit event handler isn't being called when i change the color in the color picker, any ideas?
There's no need to access the JavaFX POJO (or JavaFX Bean) directly if its properties are correctly bound to the table and also it isn't necessary to call anything other than commitEdit.
The answer from Max Beikirch is misleading, because it causes the color picker (and with it the color) to disappear when the table is not in edit mode. It's a workaround to put the table into edit mode, but a bad one. So do this before showing the color picker popup when click on the button:
Write your cell with a color picker like this:
public class ColorTableCell<T> extends TableCell<T, Color> {
private final ColorPicker colorPicker;
public ColorTableCell(TableColumn<T, Color> column) {
this.colorPicker = new ColorPicker();
this.colorPicker.editableProperty().bind(column.editableProperty());
this.colorPicker.disableProperty().bind(column.editableProperty().not());
this.colorPicker.setOnShowing(event -> {
final TableView<T> tableView = getTableView();
tableView.getSelectionModel().select(getTableRow().getIndex());
tableView.edit(tableView.getSelectionModel().getSelectedIndex(), column);
});
this.colorPicker.valueProperty().addListener((observable, oldValue, newValue) -> {
if(isEditing()) {
commitEdit(newValue);
}
});
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
#Override
protected void updateItem(Color item, boolean empty) {
super.updateItem(item, empty);
setText(null);
if(empty) {
setGraphic(null);
} else {
this.colorPicker.setValue(item);
this.setGraphic(this.colorPicker);
}
}
}
If you're on Java 7, replace the lambdas with anonymous inner classes, but it should work as well. Full blog post is here.
I had the same problem for CheckBoxTableCell and DatePickerTableCell and ColorPickerTableCells :-(
I deal it like that: on the events of the controls I get back the POJO objects in use by the "((Inputs)getTableView().getItems().get(getTableRow().getIndex()" and I update similary like is it done in the OnEditCommit method...
So for me it's look like this (update the color):
((Inputs) getTableView().getItems().get(
getTableRow().getIndex())
).setColor(cp.getValue());
Here is example with ColorPickerCell
:
public class ColorPickerTableCell<Inputs> extends TableCell<Inputs, Color>{
private ColorPicker cp;
public ColorPickerTableCell(){
cp = new ColorPicker();
cp.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
commitEdit(cp.getValue());
updateItem(cp.getValue(), isEmpty());
((Inputs) getTableView().getItems().get(
getTableRow().getIndex())
).setColor(cp.getValue());
}
});
setGraphic(cp);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setEditable(true);
}
#Override
protected void updateItem(Color item, boolean empty) {
super.updateItem(item, empty);
cp.setVisible(!empty);
this.setItem(item);
cp.setValue(item);
}
}
With this simple JavaFX's POJO:
public ObjectProperty<Color> color = new SimpleObjectProperty<Color>();
this.color = new SimpleObjectProperty(color);
public ObjectProperty<Color> colorProperty() {
return color;
}
public void setColor(Color color2) {
color.set(color2);
}
I do not know if it's a good way to achive that but it worked for me... Note that the JavaFX's POJO is only accessible within an "ActionEvent" request (combobox, datepicker, colorpicker, etc..)
Regards,
Well, I investigated that topic a bit as I have had the same problem. I am afraid to say that JavaFX is just unusable.
I took a look at how others implemented their cells and the key was that were all using something that is representable by a string.
Now, it's the way it always is with Java: Do it the Java-way or be left alone in the rain. The docs for JavaFX are extremely bad at the moment, so I had to try until it works.
So: To trigger the editCommit-event, you have to call setContentDisplay(ContentDisplay. TEXT_ONLY) in updateItem(). That works well if want to display your data as string, but fails completely in cases like these, where a colorpicker just does the job.
Alternatively, it might be possible to fire the event manually. But how do you get the table-position? I don't know.
It like Michael Simons said in the comment on the OP. You need to be in edit mode. When creating your own custom cells you can trigger edit mode manually by calling startEdit(); from inside the TableCell.
for example using the focusProperty of your control:
cp.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
startEdit();
}
});

Categories

Resources