Reputation: 397
I want to get the text in a treetable cell to overflow into the adjacent cells. I believe that I read a while ago that there is no Span function in tables or treetables, but it might be accomplished through css.
See this image. I want the date in the first cell to extend past the others so it can be read.
https://i.sstatic.net/uCtx2.jpg
I thought I would use -overflow: visible; but I read in the Oracle documentation:
JavaFX CSS does not support CSS layout properties such as float, position, overflow, and width.
Can anyone point me in the right direction here? CSS would be preferable, but would a custom TreeTableRow be the right solution?
Thanks in advance.
Upvotes: 3
Views: 1401
Reputation: 159291
Sample Solution
Here is an overflow cell for a TableView, you could probably adapt it for a TreeTableView.
class OverflowCell extends TableCell<Person, String> {
private Label overflowLabel = new Label();
private Group overflowGroup = new Group(overflowLabel);
public OverflowCell() {
// destroy the clip.
clipProperty().addListener((observable, oldClip, newClip) -> {
if (newClip != null) {
setClip(null);
}
});
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
overflowLabel.setText(item);
setGraphic(
overflowGroup
);
}
}
}
Normally the cells in a TableView are clipped, so the listener is added in the constructor of the OverflowCell to remove any clip added to the cell. The updateItem call uses a Group so that the Label is not resized to a size smaller than it's preferred size and elided.
There are probably other ways to do this. A custom row factory might be an alternate solution. This OverflowCell hack was just a simple thing which came to mind.
Sample Code
Here is it in action, you can see how the last name in the first line overflows into the next column.
Apologies for the amount of code here.
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class TableCellOverflow extends Application {
private TableView<Person> table = new TableView<>();
private final ObservableList<Person> data =
FXCollections.observableArrayList(
new Person("Jacob", "Krzyzanowski", ""),
new Person("Isabella", "Johnson", "[email protected]"),
new Person("Ethan", "Williams", "[email protected]"),
new Person("Emma", "Jones", "[email protected]"),
new Person("Michael", "Brown", "[email protected]")
);
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");
table.setPrefHeight(200);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setMaxWidth(80);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<>("firstName"));
firstNameCol.getStyleClass().add("left-header");
TableColumn<Person, String> lastNameCol = new TableColumn<>();
lastNameCol.setMaxWidth(60);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<>("lastName"));
lastNameCol.setCellFactory(param -> new OverflowCell());
TableColumn<Person, String> emailCol = new TableColumn<>("Email");
emailCol.setMaxWidth(100);
emailCol.setCellValueFactory(
new PropertyValueFactory<>("email"));
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10));
vbox.getChildren().addAll(label, table);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
class OverflowCell extends TableCell<Person, String> {
private Label overflowLabel = new Label();
private Group overflowGroup = new Group(overflowLabel);
public OverflowCell() {
// destroy the clip.
clipProperty().addListener((observable, oldClip, newClip) -> {
if (newClip != null) {
setClip(null);
}
});
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
overflowLabel.setText(item);
setGraphic(
overflowGroup
);
}
}
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty email;
private Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
}
}
Upvotes: 2