<img alt="" src="https://secure.leadforensics.com/150446.png " style="display:none;">
Go to top icon

Percent Width for TableColumn in JavaFX 2.x TableView

Sai Dandem Apr 06, 2012

TableView JavaFX Technology

The moment I started working with TableView in JavaFX 2.x, the first question raised in my mind is “Why there is no feature of setting the column widths in percentage as we do in HTML?” I am not sure what could be the reasons for not setting this feature. But if my application demands, I have to implement this by somehow ;). Ofcourse there are a couple of issues logged in JIRA related to this functionality, but till it get resolved here is the way (workaround) how I tried to get it.

And another thing is with the display of “Extra Column” in TableView. I still remember, in the discussion forum, one guy has referred this term as “Ghost Column” :). Below is the screen shot of a simple TableView, with some setting of prefWidth (here 150px) to TableColumns and resize the screen.

Ok, let me get into some action... The target is, on resizing the window the table columns should keep their relative sizes with respect to container/window.

For achieving this I am taking the help of GridPane for which percentage widths can be set to its columns through ColumnConstraints.

As a first step, a CustomTableColumn class is created that extends TableColumn, to hold the custom percentWidth property for the column.

The code for the CustomTableColumn is as below:

/**
 * CustomTableColumn to hold the custom percentWidth property.
 */
public class CustomTableColumn<s> extends TableColumn<s>{ private SimpleDoubleProperty percentWidth = new SimpleDoubleProperty(); public CustomTableColumn(String columnName){ super(columnName); } public SimpleDoubleProperty percentWidth() { return percentWidth; } public double getPercentWidth() { return percentWidth.get(); } public void setPercentWidth(double percentWidth) { this.percentWidth.set(percentWidth); } } </s></s>

The idea is that, we will create a container, probably a StackPane (CustomTableView) which holds a GridPane and a TableView. The number of columns in the GridPane will be synchronized with the number of columns in the TableView.

StackPane is used as the content in each column of the grid. (StackPane because, it fits automatically to its parent size)

Now the core logic is,

  • Step 1: We will be creating ColumnConstraints with the percentWidth that is specified for each column(CustomTableColumn) of the TableView. And set these ColumnConstraints to the grid.
  • Step 2: The next step is binding each StackPane’s widthProperty to its corresponding table column’s prefWidthProperty.

Considering the above logic, the CustomTableView code is as below:

/**
 * CustomTableView to hold the table and grid.
 */
public class CustomTableView<s> extends StackPane{ private TableView<s> table; @SuppressWarnings("rawtypes") public CustomTableView(){ this.table = new TableView<s>(); final GridPane grid = new GridPane(); this.table.getColumns().addListener(new ListChangeListener(){ @Override public void onChanged(javafx.collections.ListChangeListener.Change arg0) { grid.getColumnConstraints().clear(); ColumnConstraints[] arr1 = new ColumnConstraints[CustomTableView.this.table.getColumns().size()]; StackPane[] arr2 = new StackPane[CustomTableView.this.table.getColumns().size()]; int i=0; for(TableColumn column : CustomTableView.this.table.getColumns()){ CustomTableColumn col = (CustomTableColumn)column; ColumnConstraints consta = new ColumnConstraints(); consta.setPercentWidth(col.getPercentWidth()); StackPane sp = new StackPane(); if(i==0){ // Quick fix for not showing the horizantal scroll bar. NumberBinding diff = sp.widthProperty().subtract(3.75); column.prefWidthProperty().bind(diff); }else{ column.prefWidthProperty().bind(sp.widthProperty()); } arr1[i] = consta; arr2[i] = sp; i++; } grid.getColumnConstraints().addAll(arr1); grid.addRow(0, arr2); } }); getChildren().addAll(grid,table); } public TableView<s> getTableView(){ return this.table; } } </s></s></s></s>

Combining all the above code, the below is the final SSCCE(Short, Self Contained, Correct Example) code:

package com.ezest.javafx.demogallery.tableviews;

import javafx.application.Application;
import javafx.beans.binding.NumberBinding;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
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.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class TableViewAutoSizeDemo extends Application {

 public static void main(String[] args) {
  Application.launch(args);
 }

 @Override
 public void start(Stage stage) throws Exception {
  StackPane root = new StackPane();
  root.autosize();
  Scene scene = new Scene(root);
  stage.setTitle("TableView Auto Size Demo");
  stage.setWidth(700);
     stage.setHeight(400);
     stage.setScene(scene);
     stage.show();

  configureTable(root);
 }

 @SuppressWarnings("unchecked")
 private void configureTable(StackPane root) {

  final ObservableList data = FXCollections.observableArrayList(
     new MyDomain("Apple","This is a fruit.","Red"),
     new MyDomain("Orange","This is also a fruit.","Orange"),
     new MyDomain("Potato","This is a vegetable.","Brown")
     );

  CustomTableView table = new CustomTableView();

  CustomTableColumn titleColumn = new CustomTableColumn("Title");
  titleColumn.setPercentWidth(25);
  titleColumn.setCellValueFactory(new PropertyValueFactory("name"));

  CustomTableColumn descCol = new CustomTableColumn("Description");
  descCol.setPercentWidth(55);
  descCol.setCellValueFactory(new PropertyValueFactory("description"));

  CustomTableColumn colorCol = new CustomTableColumn("Color");
  colorCol.setPercentWidth(20);
  colorCol.setCellValueFactory(new PropertyValueFactory("color"));

  table.getTableView().getColumns().addAll(titleColumn,descCol,colorCol);
  table.getTableView().setItems(data);
  root.getChildren().add(table);
 }

 /**
  * CustomTableView to hold the table and grid.
  */
 public class CustomTableView<s> extends StackPane{ private TableView<s> table; @SuppressWarnings("rawtypes") public CustomTableView(){ this.table = new TableView<s>(); final GridPane grid = new GridPane(); this.table.getColumns().addListener(new ListChangeListener&lt;TableColumn<s>&gt;(){ public void onChanged(javafx.collections.ListChangeListener.Change arg0) { grid.getColumnConstraints().clear(); ColumnConstraints[] arr1 = new ColumnConstraints[CustomTableView.this.table.getColumns().size()]; StackPane[] arr2 = new StackPane[CustomTableView.this.table.getColumns().size()]; int i=0; for(TableColumn column : CustomTableView.this.table.getColumns()){ CustomTableColumn col = (CustomTableColumn)column; ColumnConstraints consta = new ColumnConstraints(); consta.setPercentWidth(col.getPercentWidth()); StackPane sp = new StackPane(); if(i==0){ // Quick fix for not showing the horizantal scroll bar. NumberBinding diff = sp.widthProperty().subtract(3.75); column.prefWidthProperty().bind(diff); }else{ column.prefWidthProperty().bind(sp.widthProperty()); } arr1[i] = consta; arr2[i] = sp; i++; } grid.getColumnConstraints().addAll(arr1); grid.addRow(0, arr2); } }); getChildren().addAll(grid,table); } public TableView<s> getTableView(){ return this.table; } } /** * CustomTableColumn to hold the custom percentWidth property. */ public class CustomTableColumn<s> extends TableColumn<s>{ private SimpleDoubleProperty percentWidth = new SimpleDoubleProperty(); public CustomTableColumn(String columnName){ super(columnName); } public SimpleDoubleProperty percentWidth() { return percentWidth; } public double getPercentWidth() { return percentWidth.get(); } public void setPercentWidth(double percentWidth) { this.percentWidth.set(percentWidth); } } /** * Domain Object. */ public class MyDomain{ private SimpleStringProperty name = new SimpleStringProperty(); private SimpleStringProperty description = new SimpleStringProperty(); private SimpleStringProperty color = new SimpleStringProperty(); public MyDomain(String name, String desc,String color){ this.name.set(name); this.description.set(desc); this.color.set(color); } public String getDescription() { return description.get(); } public SimpleStringProperty descriptionProperty(){ return description; } public String getName() { return name.get(); } public SimpleStringProperty nameProperty(){ return name; } public String getColor() { return color.get(); } public SimpleStringProperty colorProperty(){ return color; } } } </s></s></s></s></s></s></s>

If you find any compilation issues in the above code( due to formating), the above code can be found here.

On resizing the window, the output is as below. Not only the columns have maintained their relative sizes , but the extra column is no more visible. :)

I hope the above logic will serve the need till the auto sizing feature of TableView is implemented and released.

Happy Coding!! :)

Note: The above logic/code may be or can be improvised. Let me also know the changes for better implementation. :)

Similar Blog

Warning : This pattern is patented (http://www.google.com/patents/US20110283241). Not suitable for professional usage !!

By Sai Dandem Dec 11, 2013

JavaFX is amending day by day and adding more fasinating features over time.The interesting part is its ability to create ...

By Sai Dandem Aug 13, 2013

One of the very interesting features of JavaFX is its ability to have gradients (Linear or Radial) to the background color of the ...

By Sai Dandem Jul 19, 2012

JavaFX 2.x has many fascinating and useful controls. Among them “TabPane” is also one of the control. Here I am not going in ...

By Sai Dandem Jun 13, 2012

JavaFX animation package provides many amazing animation/transition effects. Let’s look into another effect, “Sliding” effect of ...

By Sai Dandem Apr 09, 2012

e-Zest is a leading digital innovation partner for enterprises and technology companies that utilizes emerging technologies for creating engaging customers experiences. Being a customer-focused and technology-driven company, it always helps clients in crafting holistic business value for their software development efforts. It offers software development and consulting services for cloud computing, enterprise mobility, big data and analytics, user experience and digital commerce.