6949

TreeView in a table cell Java FX 8

Question:

I have a TableView in my UI, it displays an user list from the database. One of the column of this table is editable, when editing is enabled the cell of this particular column becomes a treeview, listing various options which can be chosen.

Just to clarify, I am trying to implement a Datepicker or a colorpicker like functionality on a table cell, but with my own list of items as a tree.

The table is defined like this

private TableView<User> userTable;

The particular column which displays a tree view is defined like this

private TableColumn<User, TreeView> col4;

I set a setcellFactory method like this to display the tree

col4.setCellFactory(new Callback<TableColumn<User,TreeView>, TableCell<User,TreeView>>() { @Override public TableCell<User, TreeView> call( TableColumn<User, TreeView> param) { returns a comboboxtablecell which is filled with a tree } });

In the table, in the corresponding column, when I click the cell, the cell shows a combo box and the combobox on opening up shows the tree value.

However when the cell is in non-editable state, I am not sure how I should set the setcellValuefactory with a string value

col4.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<User,TreeView>, ObservableValue<TreeView>>() { @Override public ObservableValue<TreeView> call( CellDataFeatures< User,TreeView> param) { } }

I want to display a value which is inside the treeview as a string when the cell is in a non editable state. I am at a loss as to how to return an observablevalue of type treeview as per the method signature and still display a string.

Answer1:

You need to distinguish between the <strong>data</strong> that your TableView (and it's TableColumns) is presenting, and the cells that are used to present those data. The cellValueFactory is an object that determines how to get the value (i.e. data) for a particular column from the value for the entire row. The cellFactory is an object that determines how to get the cell that presents the data to the user.

Any time you write something like TableColumn<User, TreeView<...>> it is (almost always) a mistake. The first type in the type parameters is the type of the object in each row of the table - this is fine here - and the second is the type of the data that is displayed. TreeView is not a data type: it's the type of a UI element, i.e. the type of something that is used to display the data.

So you want something along these lines. (You haven't been too specific in explaining your data model - which is fine - but this might not be quite right; it will give you the idea though.)

TableView<User> userTable ; TableColumn<User, Options> optionsCol ;

The User class will have an ObjectProperty<Options>:

public class User { private final ObjectProperty<Options> options = new SimpleObjectProperty<>(this, "options", new Options()); public final Options getOptions() { return options.get(); } public final void setOptions(Options options) { this.options.set(options); } public ObjectProperty<Options> optionsProperty() { return options ; } // other properties, etc... }

And obviously this depends on an Options class encapsulating the data displayed in that column:

public class Options { // properties etc }

Now you just use the default cell value factory:

optionsCol.setCellValueFactory(new PropertyValueFactory("options"));

(or in JavaFX 8, I prefer

optionsCol.setCellValueFactory((TableColumn.cellDataFeatures<User, Options> data) -> data.getValue() // this is the User object .optionsProperty() // this is an ObjectProperty<Options>, which is an ObservableValue<Options> );

which is somewhat more efficient as it avoids the reflection that the PropertyValueFactory uses, and is not much more code, especially if you omit the type on the parameter to the lambda expression).

(You don't have to set it up like this. If the Options are not an intrinsic part of the User, then you could, for example, have a Map<User, ObjectProperty<Options>> defined and use that to return the ObjectProperty<Options> associated with each user. The way I showed is just the most common and probably easiest way.)

I don't really understand where your ComboBox fits in, but this answer should give you enough to work that in as you need it. The cellFactory now just has to return a TableCell that uses a TreeView to display the Options object:

optionsCol.setCellFactory( col -> new TableCell<User, Options>() { private TreeView<...> treeView ; { treeView = new TreeView<>(...); // configure tree view, etc } @Override public void updateItem(Options options, boolean empty) { super.updateItem(options, empty) ; if (empty) { setGraphic(null); } else { // configure treeView with data from options, etc setGraphic(treeView); } } });

You mentioned the cell was editable, so you need to wire up all the editing stuff for the cell too (and you'll probably want to use a named [inner] class as it's going to get a bit verbose, instead of the anonymous inner class I have here). But this should give you the basic structure.

Recommend

  • JavaFX - How to resize a SVG Path right in a TableView
  • Java fx binding styles
  • Drag and Drop working differently in Java 11 vs Java 8
  • How define differents stores for each cell combobox editor in a grid?
  • Meteor.js mongodb version
  • Zend Failed opening Zend/Application.php
  • JavaFX TableView click sorters not working?
  • Get back anonymous type [duplicate]
  • Get both date and time in milliseconds
  • Laravel 5 how to include autoload.php
  • Add a TCombobox Column to a Firemonkey TGrid
  • Save and retrieve an image file in LibGDX
  • How can I organize this data into the objects I want with LINQ?
  • Access 2007 forms with parameterized RecordSource
  • Detecting a shift + click with Jquery on Chrome
  • Set comboBox to custom display format
  • Opening links in a new tab and only the new tab
  • Using self.id to populate other fields in Django
  • draw pie chart using iOS quartz 2D
  • How to expand parent div to account for child's overflow?
  • XBee Linux Serial Port on Rasberry Pi
  • Opening two instances of InAppBrowser (_system and _blank) prevents events from triggering
  • How do you remove the JComboBox 'click and see dropdown' functionality?
  • How Get arguments value using inline assembly in C without Glibc?
  • How to make R's read_csv2() recognise the text characters properly
  • Implementation of State Monad
  • How can I set a binding to a Combox in a UserControl?
  • Ajax calls do not work in IE unless you fiddle with security settings
  • Keep this build forever option - Jenkins
  • How do I pass the string value parameter of the selected list item from an auto-populated dropdown l
  • Why ng-show works with ng-repeat but ng-if doesn't? [duplicate]
  • Controls, properties, events and timers running in design time
  • Updated Ionic CLI but shows previous version (Windows)
  • How to show dropdown in excel using jrxml (jasper api)?
  • jquery mobile loadPage not working
  • Data Validation Drop Down Box Arrow Disappearing
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • How do you join a server to an Active Directory (domain)?
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?