【问题标题】:JavaFX - Tableview filter from a TextfieldJavaFX - 来自文本字段的 Tableview 过滤器
【发布时间】:2017-09-26 16:52:25
【问题描述】:

伙计们,

希望有人能给我以下建议: 我有一个名为 packetTable 的 TableView。这个 tableView 及其 TableColumns 是从一个名为 Packet 的类中填充的。这工作正常。

我现在添加了一个名为 protoFilterField 的 TextField。这个想法是,当文本输入到这个 TextField 中时,TableView 将根据用户输入进行过滤。

我将 TextField OnAction 方法设置为 Initialize() 方法。当我运行应用程序时,我的 TableView 最初会完全填充,这是正确的。但是,如果我在我的新 TextField 中输入任何文本并点击返回,它会完全清除我的 TableView。我已尝试输入“tcp”作为我的文本,这应该是有效的并将大量记录返回到我的过滤搜索中。

谁能发现我哪里出错了?任何建议将不胜感激。

public class PacketOverviewController {
    @FXML
    private TableView<Packet> packetTable;
    @FXML
    private TableColumn<Packet, String> StartTimeColumn;
    @FXML
    private TableColumn<Packet, Double> DurColumn;
    @FXML
    private TableColumn<Packet, String> ProtoColumn;
    @FXML
    private TableColumn<Packet, String> SrcAddrColumn;
    @FXML
    private TableColumn<Packet, String> SportColumn;
    @FXML
    private TableColumn<Packet, String> DirColumn;
    @FXML
    private TableColumn<Packet, String> DstAddrColumn;
    @FXML
    private TableColumn<Packet, String> DportColumn;
    @FXML
    private TableColumn<Packet, String> StateColumn;
    @FXML
    private TableColumn<Packet, String> sTosColumn;
    @FXML
    private TableColumn<Packet, String> dTosColumn;
    @FXML
    private TableColumn<Packet, String> SrcBytesColumn;
    @FXML
    private TableColumn<Packet, String> LabelColumn;

    @FXML
    private TextField SummaryCountField;

    @FXML
    private TextField protoFilterField;

    private ObservableList<Packet> data = FXCollections.observableArrayList();  //NEW TEST


    // Reference to the main application.
    private MainApp mainApp;

    /**
     * The constructor.
     * The constructor is called before the initialize() method.
     */
    public PacketOverviewController() {

    }

    @FXML
    private void initialize() {
        StartTimeColumn.setCellValueFactory(cellData -> cellData.getValue().StartTimeProperty());
        DurColumn.setCellValueFactory(cellData -> cellData.getValue().DurProperty().asObject());
        ProtoColumn.setCellValueFactory(cellData -> cellData.getValue().ProtoProperty());
        SrcAddrColumn.setCellValueFactory(cellData -> cellData.getValue().SrcAddrProperty());
        SportColumn.setCellValueFactory(cellData -> cellData.getValue().SportProperty());
        DirColumn.setCellValueFactory(cellData -> cellData.getValue().DirProperty());
        DstAddrColumn.setCellValueFactory(cellData -> cellData.getValue().DstAddrProperty());
        DportColumn.setCellValueFactory(cellData -> cellData.getValue().DportProperty());
        StateColumn.setCellValueFactory(cellData -> cellData.getValue().StateProperty());
        sTosColumn.setCellValueFactory(cellData -> cellData.getValue().sTosProperty());
        dTosColumn.setCellValueFactory(cellData -> cellData.getValue().dTosProperty());
        //SrcBytesColumn.setCellValueFactory(cellData -> cellData.getValue().SrcBytesProperty().asObject());
        LabelColumn.setCellValueFactory(cellData -> cellData.getValue().LabelProperty());


        //NEW FILTERED FUNCTIONALITY
        FilteredList<Packet> filteredData = new FilteredList<>(data, p -> true);    //NEW TEST
        //FILTER ON THE PROTOCOL FIELD
        protoFilterField.textProperty().addListener((observable, oldValue, newValue) -> {
            filteredData.setPredicate(packet -> {
                if (newValue == null || newValue.isEmpty()){
                    return true;
                }
                System.out.println("filter test 1");
                String lowerCaseFilter = newValue.toLowerCase();

                if (packet.getProto().toLowerCase().contains(lowerCaseFilter)){
                    return true;
                }
                return false;
            });
        });

        SortedList<Packet> sortedData = new SortedList<>(filteredData);
        sortedData.comparatorProperty().bind(packetTable.comparatorProperty());
        packetTable.setItems(sortedData);
        //END NEW FILTERED FUNCTIONALITY
    }

    public void setMainApp(MainApp mainApp) {
        this.mainApp = mainApp;

        packetTable.setItems(mainApp.getPacketData());

    }
}

【问题讨论】:

  • 您在加载 FXML 文件之前是否调用了setMainApp(...)?否则我根本看不到它会如何进行任何过滤(当您调用setMainApp(...) 时,您会完全替换表格的项目列表)。您在 initialize() 方法中定义的过滤应该在您键入任何内容后立即起作用,而不是如您在问题中所述的“当您按下回车时”。所以我怀疑当文本字段上发生动作事件时,某处还有其他一些代码会导致数据消失。您应该发布minimal reproducible example(创建一个新的、完整的、列数更少的项目,并将其发布在您的问题中)。
  • 加载 FXML 文件时,我从 MainApp.java 调用 setMainApp(...)。
  • “加载时”。您显然不能在 同时 调用FXMLLoader.load() 时调用它。你是before调用load(),还是after调用load()initialize() 方法作为load 进程的一部分被调用,所以如果你在根本不使用表中的过滤列表之后调用它。
  • 在我的 load() 之后调用。
  • 在这种情况下,您需要data.setAll(mainApp.getPacketData()) 而不是您当前拥有的行。 (但我仍然怀疑您还有其他未发布的错误。)

标签: java javafx tableview filtering fxml


【解决方案1】:

您还没有真正在问题中发布足够的代码来回答这个问题,但是从 cmets 和一些假设来看,我猜您正在加载 FXML 的代码看起来像

FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/path/to/some/file.fxml"));
Parent root = loader.load();

PacketOverviewController controller = loader.getController();
controller.setMainApp(this);

那么问题将是您在initialize() 方法中将表的项目设置为过滤列表,该方法被称为load() 过程的一部分。然后随后调用setMainApp(...),它实际上用主应用程序类中定义的列表替换了这些项目(顺便说一句,这不是一个好的设计)。

您应该更新过滤列表下的列表:

public void setMainApp(MainApp mainApp) {
    this.mainApp = mainApp;

    // packetTable.setItems(mainApp.getPacketData());
    data.setAll(mainApp.getPacketData());
}

【讨论】:

    【解决方案2】:

    需要 data.setAll(mainApp.getPacketData()) 而不是我目前拥有的行。 (packetTable.setItems(mainApp.getPacketData()))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-10
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 1970-01-01
      • 2018-09-28
      • 2017-08-13
      • 1970-01-01
      相关资源
      最近更新 更多