Reputation: 6189
I have a TableView and in this TableView, there are 5 columns. One of the columns only contains the number of the row in the TableView, it simply counts them. The following behavior is what I want to achieve:
I have 5 TableView column, which I created like this:
TableColumn numberColumn = new TableColumn("#");
numberColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Vocable, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Vocable, String> vocableCellDataFeature) {
return new ReadOnlyObjectWrapper(getItems().indexOf(vocableCellDataFeature.getValue()) + "");
}
});
numberColumn.setResizable(false);
//numberColumn.setMaxWidth(numberColumn.getMaxWidth()-20);
TableColumn<Vocable, String> firstLanguageColumn = new TableColumn<>(Settings.FIRST_LANGUAGE);
firstLanguageColumn.setCellValueFactory(new PropertyValueFactory<>("firstLanguageTranslationsAsString"));
firstLanguageColumn.setMinWidth(100);
TableColumn<Vocable, String> firstLanguagePhoneticScriptColumn = new TableColumn<>(Settings.FIRST_LANGUAGE_PHONETIC_SCRIPT);
firstLanguagePhoneticScriptColumn.setCellValueFactory(new PropertyValueFactory<>("firstLanguagePhoneticScriptsAsString"));
firstLanguagePhoneticScriptColumn.setMinWidth(100);
TableColumn<Vocable, String> secondLanguagePhoneticScriptColumn = new TableColumn<>(Settings.SECOND_LANGUAGE_PHONETIC_SCRIPT);
secondLanguagePhoneticScriptColumn.setCellValueFactory(new PropertyValueFactory<>("secondLanguagePhoneticScriptsAsString"));
secondLanguagePhoneticScriptColumn.setMinWidth(100);
TableColumn<Vocable, String> secondLanguageColumn = new TableColumn<>(Settings.SECOND_LANGUAGE);
secondLanguageColumn.setCellValueFactory(new PropertyValueFactory<>("secondLanguageTranslationsAsString"));
secondLanguageColumn.setMinWidth(100);
getColumns().add(numberColumn);
getColumns().add(firstLanguageColumn);
getColumns().add(firstLanguagePhoneticScriptColumn);
getColumns().add(secondLanguagePhoneticScriptColumn);
getColumns().add(secondLanguageColumn);
getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
So my question is: How can I achieve this kind of behavior in the JavaFX TableView? Is it possible?
Upvotes: 1
Views: 3805
Reputation: 10969
Bind the column max and min widths to a fraction of the TableView width. Make the fractions add up to 1
?Col.maxWidthProperty().bind(tableView.widthProperty().multiply(.25));
?Col.minWidthProperty().bind(amountCol.maxWidthProperty());
You should really do something like this
?Col.minWidthProperty().bind(tableView.widthProperty().subtract(20).multiply(.25));
except that causes an error. It says A bound value cannot be set.
but that's not true as it only has a problem with subtraction resulting in <0. .subtract(-10)
works fine, except for not being what you want.
There must be a bug in the bindings somewhere.
edit: If you resize columns bigger than the table then you'll get a scroll bar. So when one gets bigger, others have to get smaller. I find this annoying when all columns change some percentage but maybe like this is acceptable.
import javafx.application.Application;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
public class TableTest extends Application {
@Override
public void start(Stage stage) {
ObservableList<LineItem> items = FXCollections.observableArrayList();
items.addAll(new LineItem(1,"string1","string2",123.45),
new LineItem(1,"string1","string2",123.45),
new LineItem(1,"string1","string2",123.45));
TableView<LineItem> tableView = new TableView<>(items);
TableColumn<LineItem,String> numCol = new TableColumn<>("num");
TableColumn<LineItem,String> descCol = new TableColumn<>("desc");
TableColumn<LineItem,String> nameCol = new TableColumn<>("name");
TableColumn<LineItem, Double> amountCol = new TableColumn<>("amount");
numCol.setCellValueFactory(new PropertyValueFactory<>("num"));
descCol.setCellValueFactory(new PropertyValueFactory<>("desc"));
nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
amountCol.setCellValueFactory(new PropertyValueFactory<>("amount"));
tableView.getColumns().addAll(numCol,descCol,nameCol,amountCol);
//col width logic, or lack thereof
numCol.setPrefWidth(20);
numCol.setResizable(false);
tableView.setColumnResizePolicy((TableView.ResizeFeatures param) -> {
if (param.getColumn() == null )return false;
double delta = param.getDelta();
ObservableList<TableColumn> cols = param.getTable().getColumns();
int colIdx = cols.indexOf(param.getColumn());
param.getColumn().setMinWidth(param.getColumn().getWidth() + delta);
param.getColumn().setMaxWidth(param.getColumn().getWidth() + delta);
if (colIdx < cols.size() -1){
cols.get(colIdx+1).setMinWidth(cols.get(colIdx+1).getWidth() - delta);
cols.get(colIdx+1).setMaxWidth(cols.get(colIdx+1).getWidth() - delta);
} else {
stage.setWidth(stage.getWidth() + delta);
}
return true;
});
Scene scene = new Scene(tableView);
stage.setScene(scene);
stage.show();
}
public class LineItem {
private final SimpleIntegerProperty num = new SimpleIntegerProperty();
private final SimpleStringProperty desc = new SimpleStringProperty();
private final SimpleStringProperty name = new SimpleStringProperty();
private final SimpleDoubleProperty amount = new SimpleDoubleProperty();
public SimpleIntegerProperty numProperty() {return num;}
public SimpleStringProperty descProperty() {return desc;}
public SimpleStringProperty nameProperty() {return name;}
public SimpleDoubleProperty amountProperty() {return amount;}
public LineItem(int num, String desc, String name, double amount) {
this.num.set(num);
this.desc.set(desc);
this.name.set(name);
this.amount.set(amount);
}
}
}
Upvotes: 0