Table and Columns


To use TableControl you need to call the following methods:

  1. setRecordClass(Class<T> recordClass): set the class of record (java POJO class) that will be displayed in the table. TableView will use this information to reflectively create new instance when insert button is clicked.
  2. setController(TableController<T> controller): set the controller that is responsible to load data, additionally to delete, update and insert data. TableController is an abstract class. You need to extend it and implement loadData() methods. If you want your table to have delete and save capabilities, you need to override insert(), update() and delete() methods. There are also several callback methods that could be overriden to customize TableControl’s default behaviour.
  3. addColumn(TableColumn<T, ?>... columns): add columns to table.

IMPORTANT: If the record class overrides Object’s equals(Object object) and hashCode() methods, TableView might not refresh cell’s value properly. Unless you take all records properties into account in the equals method.

To change default maximum row for all TableControls in your application, change the value of TiwulFXUtil.DEFAULT_TABLE_MAX_ROW.

To change style of changed row, check tiwulfx.css .table-row-cell:changed.


Column that display value from persistent record (POJO) extends BaseColumn. The first/sole generic type should match with TableControl’s record class. The column needs propertyName parameter in its constructor. The propertyName parameter should match with the getter and setter methods of the record class. This way the column knows what get or set methods to call. For example, if the record class is Person and it has name property, the code to create the name column will be:

TextColumn<Person> clmName = new TextColumn<>("name");

Columns that able to hold various data types i.e: ComboBoxColumn, have 2 generic type. The first is the record class and the second is the data type of property that the column will display.


This column can only handle String data type.


ComboBoxColumn could store any objects and display them as String. The second generic type is the class of data type of the column. For example, Person’s gender data type is char: ‘f’ for female and ‘m’ for male. Values that will be saved in database is either ‘f’ or ‘m’. But we need to display them as ’female’ or ‘male’ in user interface. addItem(String label, T object) method is provided to address this issue.

ComboBoxColumn<Person, Character> clmGender = new ComboBoxColumn<>("gender");
clmGender.addItem("Male", 'm');
clmGender.addItem("Female", 'f');

There is also setRequired(boolean) which need to be set to FALSE if we want to provide blank item in combobox’s list for user to unspecify value.

NumberColumn<S extends Object, T extends Number>

NumberColumn only accepts digit input. If the T generic type is Double or BigDecimal, it also accept decimal character (dot or comma) depends on the Locale. The class of the data type needs to be specified in NumberColumn’s constructor. Below is an example on how to create Integer and Double columns.

NumberColumn<Person, Integer> clmVersion = new NumberColumn<>("version", Integer.class);
NumberColumn<Person, Double> clmWeight = new NumberColumn<>("weight", Double.class);

LookupColumn<S, T> extends BaseColumn<S, T>

LookupColumn usually is used to display property that is stored in foreign table. It can displays suggestion list as well as lookup window. The suggestion list will be shown as user type in it. You can specify the delay time by calling setShowSuggestionWaitTime(int waitTime).

LookupColumn needs additional parameter besides propertyName which is lookupPropertyName. lookupPropertyName corresponds with propertyName of the object that is referred by the record. For example, Person table has many-to-one relationship with Insurance table therefore Person POJO has insurance property. To display insurance’s code that referred by a person in Person TableView, we will use LookupColumn as follow:

LookupColumn<Person, Insurance> clmInsurance = new LookupColumn<>("insurance", "code");

LookupColumn will not be able to display suggestion or lookup window without a controller that handles communication with database. Call setLookupController(LookupFieldController<T> lookupController) to set the controller.

Press Ctrl+Space to forcibly display suggestion list and press Ctrl+Enter to display lookup window.


CheckBoxColumn can only display Boolean data. Call setRequired(false) to make CheckBox cell has 3 states: TRUE, FALSE and NULL.


This column use DateControl that is based on Christian Schudt’s Date Picker. DateControl has key bindings to change the date easily. Use Up/Down to change Date, Ctrl + Up/Down to change month and Ctrl + Shift + Up/Down to change year.


Unlike the previous columns, TickColumn doesn’t display record’s value. It doesn’t extends BaseColumn. Cells of this column contain checkboxes for user to tick/untick particular rows. To get the list of ticked row, call getTickedRecords(). To get the list of unticked row call getUntickedRecords(). Developer can also call setDefaultTicked(boolean) method to set the default behaviour.

  • Conqueror

    how can I add data (rows) to the TableControl resp. TableView?

    TableView has method: setItems(…) that takes ObservableList as parameter…how about TableControl???

    • jingglang

      There is tableContro.getRecords() method than return ObservableList. However the pattern is not to use that to populate records. Use TableController.loadData() instead.

      • Conqueror

        Hi jingglang,

        I could manage to load the data now in my tableControl/tableView.

        The problem was that in your examples you are using the class.

        There was no reference to that class and I was struggling finding out what the .fetch() method does to create the data.

        In the end I figured out that you only have to return a TableData Obj with a List obj of your data you want to visualize.

        Another thing I could manage only with a workaround:
        Can you tell me how to load data into the table on init?
        I saw in a YT Video that your table was empty on startup too and you have to press the refresh button to see the data.

        I made that by first loading everything like you did and after that I wrote a method that accesses the object returned by “loader.load();” like this:

        public void setItemsAfterLoad() {
        //serviceView is the obj returned by loader.load();
        //I have a SplitPane as first child, you can have something else of course.

        SplitPane sp = (SplitPane) serviceView.getChildren().get(0);
        AnchorPane rightAnchroPane = (AnchorPane) sp.getItems().get(1);
        TableControl tC = (TableControl) rightAnchroPane.getChildren().get(0);

        Still, great work! Cheers

        • Hassan Kbbewar

          can you please give complete code for loading data on startup

          • Conqueror

            Here you go, after you setup your TableControl and Controller (this is how I did it, there are some other ways to do it, I think even better ways to do it) you simply call the reload() method and the data will be shown.

            * initialize the table controls.


            public void initTableControls() {


            * Setup TableControl


            this.tC = new TableControl();


            this.controller = new Controller();

            //custom class that provides data as List


            //give controller acces to TableControl


            //init() sets columns, column names, button icons, etc


            //give TableControl access to Controller


            //show data on startup/initialization



        • jingglang

          to load table programmatically, call


          That is the method invoked by reload button click. You can call that on application stratup.