使用SortedList对两个表进行排序

时间:2017-02-09 20:38:19

标签: javafx javafx-8

我正在尝试做与stackoverflow-17693136相关的事情。 “名字”表将用作冻结列。我在两个表中都使用了一个SortedList,并且已经将排序后的数据绑定到右边的表中。

因此,当对右表中的任一列进行排序时,对第一个名称表中的数据进行排序。但是,我还希望能够通过单击第一个名称表中的标题对右表中的列进行排序。我目前无法找到将两个表的比较器绑定到排序数据的好方法。注释掉的代码就在2下。绑定SortedList ...,你可以在TableSort.java中看到代码显示我希望我能做什么。我目前已将firstNameColumn设置为不可排序(第45行)。

此代码类似于Marko Jakob的一个例子。

TableSort2.java

package tablesort2;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class TableSort2 extends Application 
{
  private TableView<Person> personTable;
  private TableView<Person> firstNameTable;
  private TableColumn<Person, String> firstNameColumn;     // In firstNameTable
  private TableColumn<Person, String> lastNameColumn;      // In personTable
  private TableColumn<Person, Number> idValueColumn;       // In personTable

  private ObservableList<Person> masterData = FXCollections.observableArrayList();

  @Override
  public void start(Stage primaryStage) 
  {
    // Just add some sample data in the initialization
    masterData.add(new Person("Hans", "Muster", 3210));
    masterData.add(new Person("Ruth", "Mueller", 2625));
    masterData.add(new Person("Heinz", "Kurz", 1234));
    masterData.add(new Person("Cornelia", "Meier", 9999));
    masterData.add(new Person("Werner", "Meyer", 5623));
    masterData.add(new Person("Lydia", "Kunz", 7834));
    masterData.add(new Person("Anna", "Best", 2942));
    masterData.add(new Person("Stefan", "Meier", 9423));
    masterData.add(new Person("Martin", "Mueller", 9122));

    // 0. Initialize the columns
    firstNameColumn = new TableColumn("First Name");
    firstNameColumn.setSortable(false);

    lastNameColumn = new TableColumn("Last Name");
    idValueColumn = new TableColumn("Id Number");

    firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
    lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
    idValueColumn.setCellValueFactory(cellData -> cellData.getValue().idValueProperty());

    idValueColumn.setComparator((Number o1, Number o2) -> 
    {
      return (o1.intValue() < o2.intValue() ? -1 : o1.intValue() == o2.intValue() ? 0 : 1);
    });

    firstNameTable = new TableView<>();
    personTable = new TableView<>();

    // 1. Wrap the ObservableList in a SortedList.
    SortedList<Person> sortedData = new SortedList<>(masterData);

    // 2. Bind the SortedList comparator to the TableView(s) comparator.
    //sortedData.comparatorProperty().bind(firstNameTable.comparatorProperty());
    sortedData.comparatorProperty().bind(personTable.comparatorProperty());


    // 3. Add sorted data to the tables.
    firstNameTable.setItems(sortedData);
    personTable.setItems(sortedData);

    firstNameTable.getColumns().add(firstNameColumn);
    personTable.getColumns().addAll(lastNameColumn, idValueColumn);

    HBox tableBox = new HBox(5);
    tableBox.getChildren().addAll(firstNameTable, personTable);

    Scene scene = new Scene(tableBox);
    primaryStage.setScene(scene);
    primaryStage.show();
  }

  public static void main(String[] args) 
  {
    launch(args);
  }
}

Person.java

package tablesort2;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 *
 * @author dale
 */
public class Person
{
  private final StringProperty firstName;
  private final StringProperty lastName;
  private final IntegerProperty idValue;

  public Person(String firstName, String lastName, Integer id)
  {
    this.firstName = new SimpleStringProperty(firstName);
    this.lastName = new SimpleStringProperty(lastName);
    this.idValue = new SimpleIntegerProperty(id);
  }

  public String getFirstName()
  {
    return firstName.get();
  }

  public void setFirstName(String firstName)
  {
    this.firstName.set(firstName);
  }

  public StringProperty firstNameProperty()
  {
    return firstName;
  }

  public String getLastName()
  {
    return lastName.get();
  }

  public void setLastName(String lastName)
  {
    this.lastName.set(lastName);
  }

  public StringProperty lastNameProperty()
  {
    return lastName;
  }

  public Integer getIdValue()
  {
    return idValue.get();
  }

  public void setIdValue(Integer id)
  {
    this.idValue.set(id);
  }

  public IntegerProperty idValueProperty()
  {
    return idValue;
  }
}

1 个答案:

答案 0 :(得分:0)

我相信我在stackoverflow-25144215中找到了(在James_D的答案中)一些可行的东西。我可以为每列使用Label,然后使用setGraphic和Label。这允许我为每列添加事件过滤器。如果检测到MOUSE_PRESSED事件,则sortedData.comparatorProperty()将绑定到该列所在的表。这显然发生在实际排序之前。这显示在更新的TableSort2.java(下面)中。

这不适用于跨表的多列排序 - 但它不会导致此情况的异常。 (我也看到这需要我手动调整列宽以考虑标签大小。)

package tablesort2;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class TableSort2 extends Application 
{
  private TableView<Person> personTable;
  private TableView<Person> firstNameTable;
  private TableColumn<Person, String> firstNameColumn;     // In firstNameTable
  private Label firstNameLabel;                   

  private TableColumn<Person, String> lastNameColumn;      // In personTable
  private Label lastNameLabel;

  private TableColumn<Person, Number> idValueColumn;       // In personTable
  private Label idValueLabel;

  private ObservableList<Person> masterData = FXCollections.observableArrayList();

  @Override
  public void start(Stage primaryStage) 
  {
    // Just add some sample data in the initialization
    masterData.add(new Person("Hans", "Muster", 3210));
    masterData.add(new Person("Ruth", "Mueller", 2625));
    masterData.add(new Person("Heinz", "Kurz", 1234));
    masterData.add(new Person("Cornelia", "Meier", 9999));
    masterData.add(new Person("Werner", "Meyer", 5623));
    masterData.add(new Person("Lydia", "Kunz", 7834));
    masterData.add(new Person("Anna", "Best", 2942));
    masterData.add(new Person("Stefan", "Meier", 9423));
    masterData.add(new Person("Martin", "Mueller", 9122));

    // 0. Initialize the columns
    firstNameColumn = new TableColumn();
    firstNameLabel = new Label("First Name");
    firstNameColumn.setGraphic(firstNameLabel);
    //firstNameColumn.setSortable(false);

    lastNameColumn = new TableColumn();
    lastNameLabel = new Label("Last Name");
    lastNameColumn.setGraphic(lastNameLabel);

    idValueColumn = new TableColumn();
    idValueLabel = new Label("Id Number");
    idValueColumn.setGraphic(idValueLabel);

    firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
    lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
    idValueColumn.setCellValueFactory(cellData -> cellData.getValue().idValueProperty());

    idValueColumn.setComparator((Number o1, Number o2) -> 
    {
      return (o1.intValue() < o2.intValue() ? -1 : o1.intValue() == o2.intValue() ? 0 : 1);
    });

    firstNameTable = new TableView<>();
    personTable = new TableView<>();

    // 1. Wrap the ObservableList in a SortedList.
    SortedList<Person> sortedData = new SortedList<>(masterData);

    // 2. Bind the SortedList comparator (initally) to the personTable comparator.
    //sortedData.comparatorProperty().bind(firstNameTable.comparatorProperty());
    sortedData.comparatorProperty().bind(personTable.comparatorProperty());

    // 2a. Create listenters for each column header label - to update the comparator property
    firstNameLabel.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler()
    {
      @Override
      public void handle(Event event)
      {
        sortedData.comparatorProperty().bind(firstNameTable.comparatorProperty());
      }
    });

    lastNameLabel.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler()
    {
      @Override
      public void handle(Event event)
      {
        sortedData.comparatorProperty().bind(personTable.comparatorProperty());
      }
    });

    idValueLabel.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler()
    {
      @Override
      public void handle(Event event)
      {
        sortedData.comparatorProperty().bind(personTable.comparatorProperty());
      }
    });

    // 3. Add sorted data to the table.
    firstNameTable.setItems(sortedData);
    personTable.setItems(sortedData);

    firstNameTable.getColumns().add(firstNameColumn);
    personTable.getColumns().addAll(lastNameColumn, idValueColumn);

    HBox tableBox = new HBox(5);
    tableBox.getChildren().addAll(firstNameTable, personTable);

    Scene scene = new Scene(tableBox);
    primaryStage.setScene(scene);
    primaryStage.show();
  }

  public static void main(String[] args) 
  {
    launch(args);
  }
}