Thursday 5 January 2012

Percent Width for TableColumn in JavaFX 2.x TableView

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:

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:


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

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. :)

5 comments:

  1. Sai,

    It's late here so I won't have a chance to review what you're saying properly until tomorrow, but I wanted to suggest one thing in case you had the chance to review it before then.

    The TableView has a column resize policy property that specifies how to resize columns based on a given amount of change [1]. If you could code your implementation up one of these, it would be very useful. Additionally, you can look at the TableView source code in OpenJFX [2] to see how the two pre-built policies work (and you may be able to suggest improvements). They are called CONSTRAINED_RESIZE_POLICY and UNCONSTRAINED_RESIZE_POLICY.

    Feel free to email me directly with suggestions at jonathan.giles@oracle.com

    [1] http://docs.oracle.com/javafx/2.0/api/javafx/scene/control/TableView.html#columnResizePolicyProperty()

    [2] http://hg.openjdk.java.net/openjfx/2.1/master/rt/file/682bde65e6d3/javafx-ui-controls/src/javafx/scene/control/TableView.java

    ReplyDelete
  2. Jonathan,

    Thanks for taking some time to comment on this blog. :) I will definitely check the implementation of column re-size policy and will try to incur in the above functionality.

    ReplyDelete
  3. Not bad, but if you'll dragged both of two dividers to left, ghost column will appear again! :(

    Secondly, in 'Color' tab user can see strange 1 or 2 - pixel wide vertical rectangle...

    ReplyDelete
  4. I find this approach much more intuitive and much easier to use:
    http://stackoverflow.com/questions/10152828/javafx-2-automatic-column-width

    If you want to have percent, you can use:
    nameCol.prefWidthProperty().bind(personTable.widthProperty().divide(100 / 25.0));

    ReplyDelete
  5. I also used the approach of stackoverflow. Nonetheless the quickfix for the horizontal scrollbar is useful. It works if the tableview or the parent component do not generate a vertical scrollbar (i don't know which one creates the scrollbar). Does anyone have an idea how to hide the horizontal scrollbar?

    ReplyDelete