1
  1. JavaFX にObservableListはオブジェクトがありObservableList、最初のリストを反映するが各オブジェクトの文字列表現を含む別のオブジェクトが必要です。ListChangeListener変換を行うためのカスタムを書くよりも簡単なことはありますか? StringConverterミラーリングされた値を提供できる があります。

  2. 同様に、 が与えられた場合、インデックス 0 に一定のエントリがあり、インデックス 1 から始まる最初のリストを反映ObservableList<String>する秒を作成するにはどうすればよいでしょうか?ObservableList<String>

4

2 に答える 2

3

最初の質問については、これを行う最も簡単な方法は、EasyBindフレームワークを使用することです。次に、それは次のように簡単です

ObservableList<String> stringList = EasyBind.map(myBaseList, myConverter::toString);

EasyBind を使用した SSCCE を次に示します。

import org.fxmisc.easybind.EasyBind;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.util.StringConverter;


public class MappedAndTransformedListExample {

    public static void main(String[] ags) {
        ObservableList<Person> baseList = FXCollections.observableArrayList(
                new Person("Jacob", "Smith", "jacob.smith@example.com"),
                new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
                new Person("Ethan", "Williams", "ethan.williams@example.com"),
                new Person("Emma", "Jones", "emma.jones@example.com")
        );

        StringConverter<Person> converter = new StringConverter<Person>() {

            @Override
            public String toString(Person person) {
                return person.getFirstName() + " " + person.getLastName();
            }

            @Override
            public Person fromString(String string) {
                int indexOfDelimiter = string.indexOf(' ');
                return new Person(string.substring(0, indexOfDelimiter), 
                        string.substring(indexOfDelimiter+1), 
                        "");
            }

        };

        ObservableList<String> namesList = EasyBind.map(baseList, converter::toString);

        namesList.forEach(System.out::println);

        namesList.addListener((Change<? extends String> c) -> {
            while (c.next()) {
                if (c.wasAdded()) {
                    System.out.println("Added "+c.getAddedSubList());
                }
            }
        });

        System.out.println("\nAdding Michael to base list...\n");
        baseList.add(new Person("Michael", "Brown", "michael.brown@example.com"));

        namesList.forEach(System.out::println);
    }



    public static class Person {
        private final StringProperty firstName = new SimpleStringProperty(this, "firstName");
        private final StringProperty lastName = new SimpleStringProperty(this, "lastName");
        private final StringProperty email = new SimpleStringProperty(this, "email");

        public Person(String firstName, String lastName, String email) {
            this.firstName.set(firstName);
            this.lastName.set(lastName);
            this.email.set(email);
        }

        public final StringProperty firstNameProperty() {
            return this.firstName;
        }

        public final String getFirstName() {
            return this.firstNameProperty().get();
        }

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

        public final StringProperty lastNameProperty() {
            return this.lastName;
        }

        public final java.lang.String getLastName() {
            return this.lastNameProperty().get();
        }

        public final void setLastName(final java.lang.String lastName) {
            this.lastNameProperty().set(lastName);
        }

        public final StringProperty emailProperty() {
            return this.email;
        }

        public final java.lang.String getEmail() {
            return this.emailProperty().get();
        }

        public final void setEmail(final java.lang.String email) {
            this.emailProperty().set(email);
        }

    }
}

何らかの理由でサードパーティのフレームワークを使用したくない場合は、a を使用できますTransformationList(これは、EasyBind が内部で行っていることです。以下のコードをソース コードからコピーして変更しました)。

上記では、置き換えます

ObservableList<String> namesList = EasyBind.map(baseList, converter::toString);

    ObservableList<String> namesList = new TransformationList<String, Person>(baseList) {

        @Override
        public int getSourceIndex(int index) {
            return index ;
        }

        @Override
        public String get(int index) {
            return converter.toString(getSource().get(index));
        }

        @Override
        public int size() {
            return getSource().size();
        }

        @Override
        protected void sourceChanged(Change<? extends Person> c) {
            fireChange(new Change<String>(this) {
                @Override
                public boolean wasAdded() {
                    return c.wasAdded();
                }

                @Override
                public boolean wasRemoved() {
                    return c.wasRemoved();
                }

                @Override
                public boolean wasReplaced() {
                    return c.wasReplaced();
                }

                @Override
                public boolean wasUpdated() {
                    return c.wasUpdated();
                }

                @Override
                public boolean wasPermutated() {
                    return c.wasPermutated();
                }

                @Override
                public int getPermutation(int i) {
                    return c.getPermutation(i);
                }

                @Override
                protected int[] getPermutation() {
                    // This method is only called by the superclass methods
                    // wasPermutated() and getPermutation(int), which are
                    // both overriden by this class. There is no other way
                    // this method can be called.
                    throw new AssertionError("Unreachable code");
                }

                @Override
                public List<String> getRemoved() {
                    ArrayList<String> res = new ArrayList<>(c.getRemovedSize());
                    for(Person removedPerson: c.getRemoved()) {
                        res.add(converter.toString(removedPerson));
                    }
                    return res;
                }

                @Override
                public int getFrom() {
                    return c.getFrom();
                }

                @Override
                public int getTo() {
                    return c.getTo();
                }

                @Override
                public boolean next() {
                    return c.next();
                }

                @Override
                public void reset() {
                    c.reset();
                }
            });
        }


    };

2 番目の質問では、変換リストを使用する必要があります。main(...)これを行う方法を示す更新されたメソッドを次に示します。(パート 1 の 2 番目のバージョンでも同様に機能します。)

public static void main(String[] ags) {
    ObservableList<Person> baseList = FXCollections.observableArrayList(
            new Person("Jacob", "Smith", "jacob.smith@example.com"),
            new Person("Isabella", "Johnson", "isabella.johnson@example.com"),
            new Person("Ethan", "Williams", "ethan.williams@example.com"),
            new Person("Emma", "Jones", "emma.jones@example.com")
    );

    StringConverter<Person> converter = new StringConverter<Person>() {

        @Override
        public String toString(Person person) {
            return person.getFirstName() + " " + person.getLastName();
        }

        @Override
        public Person fromString(String string) {
            int indexOfDelimiter = string.indexOf(' ');
            return new Person(string.substring(0, indexOfDelimiter), 
                    string.substring(indexOfDelimiter+1), 
                    "");
        }

    };

    ObservableList<String> namesList = EasyBind.map(baseList, converter::toString);

    ObservableList<String> namesListWithHeader = new TransformationList<String, String>(namesList) {

        @Override
        public int getSourceIndex(int index) {
            return index - 1 ;
        }

        @Override
        public String get(int index) {
            if (index == 0) {
                return "Contacts";
            } else {
                return getSource().get(index - 1);
            }
        }

        @Override
        public int size() {
            return getSource().size() + 1 ;
        }

        @Override
        protected void sourceChanged(Change<? extends String> c) {
            fireChange(new Change<String>(this) {
                @Override
                public boolean wasAdded() {
                    return c.wasAdded();
                }

                @Override
                public boolean wasRemoved() {
                    return c.wasRemoved();
                }

                @Override
                public boolean wasReplaced() {
                    return c.wasReplaced();
                }

                @Override
                public boolean wasUpdated() {
                    return c.wasUpdated();
                }

                @Override
                public boolean wasPermutated() {
                    return c.wasPermutated();
                }

                @Override
                public int getPermutation(int i) {
                    return c.getPermutation(i - 1) + 1;
                }

                @Override
                protected int[] getPermutation() {
                    // This method is only called by the superclass methods
                    // wasPermutated() and getPermutation(int), which are
                    // both overriden by this class. There is no other way
                    // this method can be called.
                    throw new AssertionError("Unreachable code");
                }

                @Override
                public List<String> getRemoved() {
                    ArrayList<String> res = new ArrayList<>(c.getRemovedSize());
                    for(String removed: c.getRemoved()) {
                        res.add(removed);
                    }
                    return res;
                }

                @Override
                public int getFrom() {
                    return c.getFrom() + 1;
                }

                @Override
                public int getTo() {
                    return c.getTo() + 1;
                }

                @Override
                public boolean next() {
                    return c.next();
                }

                @Override
                public void reset() {
                    c.reset();
                }
            });
        }

    };

    namesListWithHeader.forEach(System.out::println);

    namesListWithHeader.addListener((Change<? extends String> c) -> {
        while (c.next()) {
            if (c.wasAdded()) {
                System.out.println("Added "+c.getAddedSubList());
                System.out.println("From: "+c.getFrom()+", To: "+c.getTo());
            }
        }
    });

    System.out.println("\nAdding Michael to base list...\n");
    baseList.add(new Person("Michael", "Brown", "michael.brown@example.com"));

    namesListWithHeader.forEach(System.out::println);
}
于 2015-08-30T13:50:42.660 に答える