Hello and Welcome . Today I would like to blog about the TableView of Javafx 2.0 beta b_45. If you are new to the TableView then please have a look at these class files.
The java documentation of those classes are very important for you when developing the application.
Let’s start here. First the thing what I’m going to show you is about the Cell which is the intersection of any row and column. Before going to TableCell , you can go for the TableColumn which helps to take control over the TableCell with cellFactory. The TableColumn is the column of any table which defines the new column with it’s defined named. Let’s make four columns our Test. I’m running these codes with compatible to JavaFX 2.0 build 45. So it might varies on future or on previous version of javafx.
TableColumn Defination
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
TableColumn albumArt = new TableColumn("Album Art"); albumArt.setCellValueFactory(new PropertyValueFactory("album")); albumArt.setPrefWidth(200); TableColumn title = new TableColumn("Title"); title.setCellValueFactory(new PropertyValueFactory("title")); title.setPrefWidth(120); TableColumn artist = new TableColumn("Artist"); artist.setCellValueFactory(new PropertyValueFactory("artist")); artist.setPrefWidth(120); TableColumn rating = new TableColumn("Rating"); rating.setCellValueFactory(new PropertyValueFactory("rating")); rating.setPrefWidth(120); |
There is nothing hard. It’s all simple Object with setMethods. The PropertyValueFactory might be new for you. We are using the propertyvalueFactory with “album”, “title” , “artist” , “rating” because these properties are going to be implemented in our Object Class (Music.java).
Music.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
/** * * @author Narayan */ public class Music { //Properties private SimpleStringProperty artist = new SimpleStringProperty(); private ObjectProperty albumArt= new SimpleObjectProperty(); private StringProperty title= new SimpleStringProperty(); private IntegerProperty rating= new SimpleIntegerProperty(); public Music(String artist,Album album, String title, Integer rating) { setArtist(artist); setAlbum(album); setTitle(title); setRating(rating); } //For Artist public void setArtist(String art){ artist.set(art); } public String getArtist(){ return artist.get(); } public StringProperty artistProperty(){ return artist; } //For Album public void setAlbum(Album alb){ albumArt.set(alb); } public Object getAlbum(){ return albumArt.get(); } public ObjectProperty albumProperty(){ return albumArt; } //For Title public void setTitle(String tit){ title.set(tit); } public String getTitle(){ return title.get(); } public StringProperty titleProperty(){ return title; } //For Rating public void setRating(int rat){ rating.set(rat); } public Integer getRating(){ return rating.get(); } public IntegerProperty ratingProperty(){ return rating; } } |
In above Music you may see Album Class which is another Class which defines brief of any album. Currently I’m just making these things easier for sample.The Album class is given below.
Album.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/** * * @author Narayan */ public class Album { //Attributes private String filename; private String artist; private String album; public Album(String filename, String artist, String album) { this.filename = filename; this.artist = artist; this.album = album; } //Accessor Methods public String getAlbum() { return album; } public void setAlbum(String album) { this.album = album; } public String getArtist() { return artist; } public void setArtist(String artist) { this.artist = artist; } public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } } |
We ‘ll be using Music class as the Generic Class which will be used in the TableView. So to make our TableView Object friendly we need to make the TableView like this:
1 2 |
TableView<Music> table = new TableView<Music>(); table.setTableMenuButtonVisible(true); |
CellFactory
I know you guys might be eager to make your TableCell more customize so to make cell more customizable there is the setCellFactory in Table Column. This function helps to set you own cellFactory. We’ll be customizing only two column’s cell. They are Rating and Album Art. Let’s do these stuffs one by one.
1. Rating Cell Customize
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
" ]// SETTING THE CELL FACTORY FOR THE RATINGS COLUMN rating.setCellFactory(new Callback<TableColumn<Music,Integer>,TableCell<Music,Integer>>(){ @Override public TableCell<Music, Integer> call(TableColumn<Music, Integer> param) { TableCell<Music, Integer> cell = new TableCell<Music, Integer>(){ @Override public void updateItem(Integer item, boolean empty) { if(item!=null){ ChoiceBox choice = new ChoiceBox(ratingSample); choice.getSelectionModel().select(ratingSample.indexOf(item)); //SETTING ALL THE GRAPHICS COMPONENT FOR CELL setGraphic(choice); } } }; return cell; } }); |
In above cell factory I’m using Music Generic class for TableColumn of Callback Object.Now we are making the TableCell Object overriding updateItem function. Here we’ve used inherited setGraphic function of TableCell class for setting the Graphics of any cell. In this way you can set any graphic for cell. I’ve used ChoiceBox for setting the graphics. The ratingSample is the final variable consisting the possible rating values of any music.
2. AlbumArt Cell Customize
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
" ]// SETTING THE CELL FACTORY FOR THE ALBUM ART albumArt.setCellFactory(new Callback<TableColumn<Music,Album>,TableCell<Music,Album>>(){ @Override public TableCell<Music, Album> call(TableColumn<Music, Album> param) { TableCell<Music, Album> cell = new TableCell<Music, Album>(){ ImageView imageview = new ImageView(); @Override public void updateItem(Album item, boolean empty) { if(item!=null){ HBox box= new HBox(); box.setSpacing(10) ; VBox vbox = new VBox(); vbox.getChildren().add(new Label(item.getArtist())); vbox.getChildren().add(new Label(item.getAlbum())); imageview.setFitHeight(50); imageview.setFitWidth(50); imageview.setImage(new Image(MusicTable.class.getResource("img").toString()+"/"+item.getFilename())); box.getChildren().addAll(imageview,vbox); //SETTING ALL THE GRAPHICS COMPONENT FOR CELL setGraphic(box); } } }; System.out.println(cell.getIndex()); return cell; } }); |
In above cell factory, I’ve used my own kind of graphics. I this one cell factory is similar to previous one. Here I used the images resources of my own package “/img” .
Finally you ‘ve really customized the Cell of the table now it’s time for adding those columns and rows to table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//SAMPLE DATAS ObservableList artists = FXCollections.observableArrayList("Adele", "Unknown","Beyounce","Rihanna","Avril","Disturbia","Kid Rock","Jessi J","Unknown","Unknown"); ObservableList titles = FXCollections.observableArrayList("Running in the Deep", "Title 01","Title 09","What's my name","What the Hell","Disturbia","Kid Rock","Price Tag","Title 2","09"); //ADDING ALL THE COLUMNS TO TABLEVIEW table.getColumns().addAll(albumArt,title,artist,rating); //ADDING ROWS INTO TABLEVIEW ObservableList musics = FXCollections.observableArrayList(); for(int i = 0; i<10; i++){ Album al = new Album(i+1+".jpg",artists.get(i),artists.get(i)); Music m = new Music(artists.get(i),al,titles.get(i),i%5); musics.add(m); } table.setItems(musics); |
Fancy Stuffs
To make your table more fancy Let’s do some fancy stuffs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public Group getBackground(){ Group group = new Group(); group.setLayoutX(40); group.setLayoutY(40); Rectangle rect = new Rectangle(); rect.setWidth(600); rect.setHeight(460); rect.setFill(Color.web("#f5f5f5")); //Some OuterGlow Effect rect.setEffect(DropShadowBuilder.create(). color(Color.web("#969696")). offsetX(0).offsetY(0).radius(50).spread(0.2) .build()); group.getChildren().add(rect); return group; } |
You can implement these things in your Application start() function like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
@Override public void start(Stage stage) throws Exception { //Main Group of the Application Group group = getBackground(); //VBox for the Text and Table VBox box = new VBox(); box.setLayoutX(20); box.setLayoutY(5); box.setSpacing(15); //Text Text text = new Text("Music Library"); text.setFont(new Font(20)); //Table TableView table = getTableView(); //here i used all the TableView in a function table.setLayoutX(20); table.setLayoutY(20); //adding all components box.getChildren().addAll(text,table); group.getChildren().add(box); Scene scene = new Scene(group,680,530,Color.web("#666666")); stage.setScene(scene); stage.show(); } |
Finally your output will be like this:
The full source code is here : MusicLibrary Project
Ok This much for day . If you have any problem then please comment. Have a good 🙂 day.
Thanks.
great ! keep blogging … ;o)
Good job… but, how can you recover data from a selected row?. For example the rating of Avril disc (4)
Hi leojim,
It’s not a big deal. We can easily save the rating of Avril disc by setting the value of ObservableList ‘musics’ item. You need to register a new listener of Mouse when the ComboBox of Avril is selected then change the value of ‘musics’ item according to the user’s selection.
Thanks.
Narayan
Oh! Thank you so much…………….^^
Very good example. Does your code provide bidirectional binding? I wanted to use a cell factory to put checkboxes in a column of a tableView. When the checkbox is selected, the property associated with that column should be updated. It looks like your design would work, substituting the choicebox references with checkbox code.
Hi Ryan,
To make the event handling on the checkbox and it’s effect to real beans then you need to EventHandler to the control. Currently in the context of this post. I can add changelistener to the choicebox “value” inside which is declared inside CellFactory .
Inside the listener override method you can edit the value of main ObservableList (variable “musics” in this context) and the effect will be in bi-directional.
Thanks
Thank you, great job…
Thank you. That was easy to follow and understand.
Great job. congratulations!
I have a situation and would ask directions, I’m new to JavaFX and must develop a screen similar to an excel spreadsheet. I have a bean that stores the value of the cell and the position (x, y). Each cell is a value entered in the database, and spreadsheet size may vary, eg 16×16, 10×10 etc.
How do I generate a dynamic table for this situation and take the position of each cell to enter the bean x,y atributes, for latter show and edit again?
Would you like help-me with your experience with JavaFX to guide me.
Thank you. Cheers
Have you checked out the dynamic TableView post of mine ? https://blog.ngopal.com.np/2011/10/19/dyanmic-tableview-data-from-database/
Thanks
Narayan
Could you please explain how do I make these values editable? Especially the album art.
Hi @Muhammad,
The answer is somehow same to #6 comment 🙂
Make the Cell editable using the editableProperty of Cell which is inherited by TableCell and you can also refer to TableCellEdit of Oracle tutorial for your help to understand how the edit function actually works in normal text data table cell.
Thanks
Narayan
Pingback: ListView Animation « Java and FX
I would like to see an example where a cell is a URL Hyperlink, You can click and invoke a browser….
Any hint?
Thanks,
Tan
You can have some hints for executing http links from java from here: https://blog.ngopal.com.np/2011/02/09/open-default-browser-in-javafx/
Thanks
Narayan
I know how to open web browser with URL.
I would like to know how to add a Hyperlink in a table column. Or custom TableCell, so user can click the link and open browser with provided URL.
Or like in your example, if we add another column with Hyperlink, when user click on the link, we will play the song with provided URL.
Thanks,
Tan
In the section 2. when you are setting up Album Art cell drawing mechanism, you are creating a new ImageView every time cell is drawn. You should take the ImageView creation out of the updateItem method to avoid extra memory allocation and slowness.
Thanks for the update 🙂
Hi Mr Narayan. I wish to know how fill a table with values coming from 2 or more different tables in database..
I am stuck, please help.. I want to use joins and display the list in the table but after trying all d combinations, i ended up displaying a table with empty values.
Please help
Great tutorial , how would I be able to filter the data. Im having trouble . the content of some row that should be filtered still display .
Thank you very much