0

I'm currently trying to add some images from a decoded video to a TableView row and they are not appearing. Only empty TableColumns. The TableView has been designed in JavaFx Scene Builder along with the Label.

Here's what I got so far:

public class MainScreenController implements Initializable {

@FXML
private Label previewBoxLabel;

@FXML
private TableView tableView;

private ObservableList<ImageView> imageList = FXCollections.observableArrayList();

@FXML
public void AddClipBeta(){

    //Code which uses an external class in order to decode video (Variables Frames, width and height are not shown but are present in the actual code)
    VideoSegment clip = new VideoSegment(0, file.getPath(), 0, Frames, width, height);

//Opens the file in decoding class - ready to output frames        
    try{clip.openFile();} catch(Exception e){}

//First frame is updated on the preview box
    previewBoxLabel.setGraphic(new ImageView(convertToFxImage(clip.getThumbnail())));


    System.out.println(file.getPath());
    int i =0;

//While loop in test phase to see whether or not 10 frames will be visible in the table
    while(i != 10){

    //Creates and sets columns to tableView
        TableColumn<ImageView, ImageView> col = new TableColumn<ImageView, ImageView>();
        col.setPrefWidth(100); //Set width of column
        tableView.getColumns().add(col);

        col.setCellFactory(new Callback<TableColumn<ImageView, ImageView>, TableCell<ImageView, ImageView>>() {

            @Override
            public TableCell<ImageView, ImageView> call(TableColumn<ImageView, ImageView> p) {


                    TableCell<ImageView, ImageView> cell = new TableCell<ImageView, ImageView>(){
                    };

                    return cell;
            }


        });

    //Adds current frame to list
        imageList.add(new ImageView(convertToFxImage(clip.getThumbnail())));

    //Gets next video frame
        try{clip.getNextFrame();} catch(Exception e){}

    //Updates counter 
        i++;
    }

//Sets list of frames on the table 
    tableView.setItems(imageList);


}

// There is a problem with this implementation: transparent pixels on the BufferedImage aren't converted to transparent pixels on the fxImage.
public static javafx.scene.image.Image convertToFxImage(java.awt.image.BufferedImage awtImage) {
    if (Image.impl_isExternalFormatSupported(BufferedImage.class)) {
        return javafx.scene.image.Image.impl_fromExternalImage(awtImage);
    } else {
        return null;
    }
}

I've been struggling understanding how the TableView works the last couple of days and it would be a real breakthrough if we could get to the bottom of this.

Thanks for reading and any help in advance!

Mally
  • 17
  • 6
  • Have a look at the tutorial. Start with [ListView](http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/list-view.htm#CEGGEDBF), which is simpler, but example 12-4 will give you an idea how cells work in general. Then maybe read through the [TableView](http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm#CJAGAAEE) tutorial. – James_D Apr 03 '14 at 17:00
  • Will do! Hopefully, I can get the hang of this. – Mally Apr 04 '14 at 11:27

2 Answers2

0

When setting a CellFactory, you need to take in to account that it will override some default bevaiours such as setting text and images.

For example. I had to create a ListView of Applications that launched on double click. I had to set a CellFactory in order to add a listener to the mouse click of each individual cell.

applications.setCellFactory(new Callback<TreeView<Application>, TreeCell<Application>>() {

        @Override
        public TreeCell<Application> call(TreeView<Application> param) {
            return new TreeCell<Application>() {

                @Override
                protected void updateItem(Application item, boolean empty) {
                    //call the origional update first
                    super.updateItem(item, empty); 
                    //the root item in my list is null, this check is required to keep a null pointer from happening
                    if (item != null) {
                        // text and graphic are stored in the Application object and set.
                        this.setText(item.getApplicationListName());
                        this.setGraphic(item.getGraphic());

                        // registers the mouse event to the cell.
                        this.setOnMouseClicked((MouseEvent e) -> {
                            if (e.getClickCount() == 2) {
                                try {
                                    this.getItem().launch(tabBar);
                                } catch (UnsupportedOperationException ex) {
                                    Dialogs.create().nativeTitleBar().masthead("Comming Soon™").message("Application is still in development and will be available Soon™").nativeTitleBar().title("Unavailable").showInformation();
                                }
                            } else {
                                e.consume();
                            }

                        });
                    }else if(empty){
                        this.setText(null);
                        this.setGraphic(null);
                        this.setOnMouseClicked(null);
                    }
                }
            };
        }
    });

This was pieced together from some other code so if there is anything else you would like explained, let me know!

LinkXXI
  • 314
  • 2
  • 13
  • I understand your code but the problem I'm having is actually adding the content to the cells. Do I need to create a class with getters and setters and reference it to the table, list and cells? – Mally Apr 04 '14 at 11:25
  • You need to separate the data from its presentation. If the data type for your TableView is some type of Node (ImageView in your case), that's almost always a mistake. First figure out what kind of data you are presenting in each row, then figure out what data each column will present from the corresponding row data. That's your cellValueFactory. Then figure out how to actually present those data to the user in the cell. That's your cellFactory. – James_D Apr 04 '14 at 12:08
  • @James_D is right. I'd say if you do wan't to display a node in the table for some reason, the best thing to do is to make a wrapper class of some sort with getters and setters instead of making it directly of that node type. Also, `CellValueFactory` and `CellFactory` are two fairly different beasts depending on exacty what you want to do. `CellFactory` allows you to over-ride the default bevaior of the cell it's self. `CellValueFactory` lets you define a specific property of the class the table is made out of to display in that cell. `Cell Factory` lets you change a cell's behaviour. – LinkXXI Apr 04 '14 at 12:29
  • @LinkXXI Thanks a lot, guys :) I managed to insert the data in the end of the day. By any chance, would you guys know how to add an array of data to a row as opposed to only a column? – Mally Apr 06 '14 at 20:41
0

I managed to sort this out with the help of you guys. Basically, what I did was make a class with a bunch of setters and getters and a constructor that takes in ImageViews and sets it to a variable in the class via it's constructors. Then I went back to my code and added the following:

Class with Getters and Setters:

import javafx.scene.image.ImageView;


public class tableDataModel {

private ImageView image;  

public tableDataModel(ImageView image){
    this.image = image;
}

public ImageView getImage(){
    return image; 
}

public void setImage(ImageView image){
    this.image = image;
}

}

Code from MainScreenController:

    TableColumn<tableDataModel, ImageView> col = new TableColumn<>();
    tableView.getColumns().add(col);
    imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getThumbnail()))));
col.setPrefWidth(50);
    col.setCellValueFactory(new PropertyValueFactory<tableDataModel, ImageView>("image"));

    int i = 0;
    while (i != 10) {



    try {
            imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getNextFrame()))));
        } catch (Exception e) {
        }
        i++;
}
tableView.setItems(imageList);
Mally
  • 17
  • 6