对自定义javafx listview单元进行故障排除

时间:2019-07-12 09:23:00

标签: java javafx

列表视图单元格加载空白而不是自定义单元格

我尝试使用调试工具重建fxml文件,但这些方法都无济于事。我在网上进行了广泛研究,但只能找到有关Javafx listview较旧版本的指南。

在有人告诉我updateItem代码是错误的之前,请先帮助我使其工作,然后至少可以从某个地方开始对其进行优化

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");
        }
    }

}

我的预期结果是将数据加载到自定义单元格中然后显示它,它的实际作用是给我一个空白单元格

1 个答案:

答案 0 :(得分:0)

似乎您创建了ListCellController2类的两个实例。

  • 您在列表视图单元工厂中创建第一个实例
  • 第二个实例是在您加载FXML时创建的,因为在FXML内部提供了控制器类

我还建议您在创建单元格时只加载一次列表单元组件,而不是每次显示新值时都加载。

控制器由单元工厂创建,实例由FXML-loader使用。这样,用@FXML注释的字段将被正确初始化。

这是我的代码:

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>