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);
}
}
};
});
Related
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:
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;
}
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
I put the numbers in my textfields located in Mirror column, But when I handle the scroll bar (scroll my table), the contents of the textfields are deleted. Is there any solution to this problem?
The code that creates my table:
#SuppressWarnings({ "unchecked", "rawtypes" })
private void loadTabMirror() {
TableColumn request = new TableColumn("Pedido");
request.setCellValueFactory(new PropertyValueFactory<MirrorVo, String>("request"));
request.setMinWidth(150);
TableColumn applicant = new TableColumn("Requerente");
applicant.setCellValueFactory(new PropertyValueFactory<MirrorVo, String>("name"));
applicant.setMinWidth(400);
TableColumn numberRg = new TableColumn("N° RG");
numberRg.setCellValueFactory(new PropertyValueFactory<MirrorVo, String>("rg"));
numberRg.setMinWidth(80);
Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>> txtMirrorCallBack =
new Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>>() {
#Override
public TableCell call(final TableColumn param) {
final TableCell cell = new TableCell() {
#Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else if(item == null){
TextField textField = loadRuleTextField(param,getIndex());
textFieldMirrors.add(textField);
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
}
};
return cell;
}
};
TableColumn mirror = new TableColumn("Espelho");
mirror.setCellValueFactory(new PropertyValueFactory<MirrorVo, Integer>("mirror"));
mirror.setMinWidth(100);
mirror.setCellFactory(txtMirrorCallBack);
Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>> imgMirrorInfo =
new Callback<TableColumn<MirrorVo, String>, TableCell<MirrorVo, String>>() {
#Override
public TableCell<MirrorVo, String> call(
TableColumn<MirrorVo, String> param) {
final TableCell cell = new TableCell() {
#Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
ImageView imgViewInfo = new ImageView(new Image("resources/img/info.png"));
imgViewInfo.setFitWidth(32);
imgViewInfo.setFitHeight(32);
imgViewInfo.setVisible(false);
imgViewInfos.put(getIndex(), imgViewInfo);
setGraphic(imgViewInfo);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
}
};
return cell;
}
};
TableColumn info = new TableColumn("Status");
info.setMinWidth(40);
info.setCellFactory(imgMirrorInfo);
Callback<TableColumn<CivilRecord, String>, TableCell<CivilRecord, String>> btnInvalidateCallBack = addActionBtnInvalidate();
TableColumn validation = new TableColumn(" ");
validation.setCellValueFactory(new PropertyValueFactory<CivilRecord, String>("dateRegisterLot"));
validation.setMinWidth(100);
validation.setCellFactory(btnInvalidateCallBack);
Callback<TableColumn<CivilRecord, String>, TableCell<CivilRecord, String>> btnAutoGenerateCallBack = addActionBtnAutoGenerate();
TableColumn autoGenerate = new TableColumn(" ");
autoGenerate.setCellValueFactory(new PropertyValueFactory<CivilRecord, String>("dateRegisterLot"));
autoGenerate.setMinWidth(100);
autoGenerate.setCellFactory(btnAutoGenerateCallBack);
tabMirror.getColumns().addAll(request,applicant,numberRg,mirror,info,autoGenerate, validation);
}
Your TableCell for the mirror column never actually handles the case where the item has content (i.e. the item is not null).
As you scroll, what probably happens is that TableCells which are scrolled off the visible portion of the screen get updated as empty cells, then they get reused at some point for new items that are displayed. So the updateItem() method is first called with empty=true (setting the text and graphic to null), and is later called with empty=false and item as the item to be displayed. Since your updateItem method doesn't handle this case at all, the cell's text and graphic remain null.
You need to change the updateItem method so that it handles all possible cases:
empty == true (you already have)
empty == false && item == null (you already have)
empty == false && item != null (you do not handle)
I have a TableView Column set up as follows, with some text in a Text node. I wanted to style up the text, but the only css property being picked up is the italics. How can I associate the text with other properties such as color.
I've tried text.getStyleClass().add("table-text-allign-top-left"); but only italics gets picked up.
I'd also like to add some kind of spacing, like padding, but I don't know how to add such to an item in a TableCell.
The other problem is how to align items: to the left' right in a TableCell.
Would appreciate it a lot if anyone could help. Thank you all in advance.
This is an extract of the TableView:
clientNames.setCellFactory(new Callback<TableColumn<NewClientPOJO, String>, TableCell<NewClientPOJO, String>>() {
#Override
public TableCell<NewClientPOJO, String> call(TableColumn<NewClientPOJO, String> param) {
final TableCell<NewClientPOJO, String> cell = new TableCell<NewClientPOJO, String>() {
private Text text;
private Text emails;
private Text emails2;
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty()) {
text = new Text(item.toString());
// Setting the wrapping width to the Text
text.setWrappingWidth(410);
text.getStyleClass().add("table-text-allign-top-left");
emails = new Text("Good DW TV");
emails.getStyleClass().add("lower");
emails2 = new Text("Scandinavia - Lines cold weather");
emails2.getStyleClass().add("lower");
VBox vbTable = new VBox();
vbTable.getChildren().add(text);
vbTable.getChildren().add(emails);
vbTable.getChildren().add(emails2);
setGraphic(vbTable);
}
}
};
return cell;
}
});
Thanks brian for the reply. I got it to work by changing the Node from Text to a Label. The Label picks up the style class.