简体   繁体   中英

troubleshooting custom javafx listview cell

Listview cells loading blank instead of custom cell

I've tried rebuilding fxml file, using debug tools, none of these have helped.I've looked extensively on the net but can only find guides for older versions of javafx listview.

Before some tells me that the updateItem code is wrong, please just help me get it working first, then at least it'll be somewhere to start from for optimizing it

package Test;

import java.io.IOException;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.Pane;
import org.controlsfx.glyphfont.Glyph;

/**
 * FXML Controller class
 *
 * @author james
 */
public class ListCellController2 extends ListCell<Student>
{
    FXMLLoader loader;

    @FXML
    private Glyph attendenceSymbolGlyph;
    @FXML
    private Label studentDetailsLabel;
    @FXML
    private Pane entryPane;

   @Override
   protected void updateItem(Student student, boolean empty)
   {
       super.updateItem(student, empty);

       if (empty || student == null)
       {
           setText(null);
           setGraphic(null);
       }
       else
       {
           loader = new FXMLLoader(getClass().getResource("ListCell2.fxml"));
           try
           {
               loader.load();
               studentDetailsLabel.setText(student.toString());
               setGraphic(entryPane);
           }
           catch (IOException ex)
           {
               ex.printStackTrace();
           }
       }
   }
}
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<?import org.controlsfx.glyphfont.Glyph?>

<Pane fx:id="entryPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="95.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Test.ListCellController2">
   <children>
      <Glyph id="attendenceSymbolGlyph" fx:id="attendenceSymbolGlyph" layoutX="5.0" layoutY="8.0" prefHeight="80.0" prefWidth="87.0" />
      <Label id="studentDetailsLabel" fx:id="studentDetailsLabel" layoutX="113.0" layoutY="5.0" prefHeight="88.0" prefWidth="482.0" text="Label" />
   </children>
</Pane>
package Test;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.util.Callback;

/**
 * FXML Controller class
 *
 * @author james
 */
public class MainController implements Initializable {

    @FXML
    public ListView<Student> myListView;
    public ObservableList<Student> studentList;

    public MainController() 
    {
        studentList = FXCollections.observableArrayList();

        studentList.add(new Student("Jimmy", "u0764987", "ef937b3"));
        studentList.add(new Student("John", "u0762809", "543jh32"));
    }

    public void setupListView()
    {
        try
        {
            myListView.setItems((ObservableList)studentList);
            myListView.setCellFactory(new Callback<ListView<Student>, ListCell<Student>>()
            {
                @Override
                public ListCell<Student> call(ListView<Student> p) 
                {
                    return new ListCellController();
                }

            });
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) 
    {
        if (!studentList.isEmpty())
        {
            setupListView();
        }
        else
        {
            System.out.println("student list is empty");
        }
    }

}

My expected result would be that it loads my data into the custom cell then displays it, what it actually does is is give me a blank cell

It seems you created two instances of your ListCellController2 class.

  • you create the first instance in your list view cell factory
  • the second instance is created when you load the FXML as the controller class is given inside the FXML

I also suggest you only load the list cell component once when your cell is created, instead of every time a new value is shown.

The controller is created by the cell factory and the instance is used by the FXML-loader. This way, the fields annotated with @FXML get initialized correctly.

Here is my code:

MainController.java

import java.net.URL;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListView;

public class MainController implements Initializable {

    @FXML
    public ListView<Student> myListView;
    public ObservableList<Student> studentList;

    public MainController() {
        studentList = FXCollections.observableArrayList();
        studentList.add(new Student("Jimmy", "u0764987", "ef937b3"));
        studentList.add(new Student("John", "u0762809", "543jh32"));
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        if (!studentList.isEmpty()) {
            setupListView();
        } else {
            System.out.println("student list is empty");
        }
    }

    private void setupListView() {
        myListView.setItems(studentList);
        myListView.setCellFactory((listView) -> new ListCellController2());
    }
}

ListCellController2

import java.io.IOException;
import org.controlsfx.glyphfont.Glyph;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.Pane;

public class ListCellController2 extends ListCell<Student> {

    @FXML
    private Glyph attendenceSymbolGlyph;
    @FXML
    private Label studentDetailsLabel;
    @FXML
    private Pane entryPane;

    public ListCellController2() {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setController(this);
            loader.setLocation(getClass().getResource("ListCell2.fxml"));
            loader.load();
        } catch (IOException e) {
            throw new RuntimeException("Creating UI component failed", e);
        }
    }

    @Override
    protected void updateItem(Student student, boolean empty) {
        super.updateItem(student, empty);

        if (empty || student == null) {
            setText(null);
            setGraphic(null);
        } else {
            studentDetailsLabel.setText(student.toString());
            setGraphic(entryPane);
        }
    }
}

ListCell2.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<?import org.controlsfx.glyphfont.Glyph?>

<Pane fx:id="entryPane" prefHeight="95.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Glyph id="attendenceSymbolGlyph" fx:id="attendenceSymbolGlyph" layoutX="5.0" layoutY="8.0" prefHeight="80.0" prefWidth="87.0" />
      <Label id="studentDetailsLabel" fx:id="studentDetailsLabel" layoutX="113.0" layoutY="5.0" prefHeight="88.0" prefWidth="482.0" text="Label" />
   </children>
</Pane>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM