Добрый день
Есть список объектов BooleanProperty, в который время от времени добавляются новые объекты (отрезки времени не одинаковые), изначально все эти объекты инициализированы со значением true. Так же в процессе работы программы у некоторых объектов из этого списка значение меняется на false (отрезки времени не одинаковые). Доступа к методу который меняет данное значение нет, то есть можно только слушать объекты списка. Heобходимо, что бы после изменения объекта, он удалялся из данного списка, а его индекс передавался в некоторый метод. Написал упрощенное решение того что нужно, но все работает как-то не так. При первом изменении удаления не происходит, при втором изменении удаляется объект с индексом 1, далее получаем исключение IndexOutOfBoundsException
package example;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
public class Main {
private static final List<BooleanProperty> LIST = new ArrayList<>();
public static void main(String[] args) {
fillList(3);
change(3);
}
private static void fillList(int count) {
for (int i=0; i<count; i++) {
int time = (int) (Math.random() * 10000 + 1000);
try {
Thread.sleep(time);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
LIST.add(new SimpleBooleanProperty(true));
}
}
private static void change(int count) {
for (int i=0; i<count; i++) {
int time = (int) (Math.random() * 10000 + 1000);
try {
Thread.sleep(time);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
switch (i + 1) {
case 1:
LIST.get(i).set(false);
listner();
break;
case 2:
LIST.get(i).set(false);
listner();
break;
case 3:
LIST.get(i).set(false);
listner();
break;
default:
break;
}
}
}
private static void listner() {
for (int i=0; i<LIST.size(); i++) {
int step = i;
LIST.get(i).addListener((observable, oldValue, newValue) -> {
if (!newValue) {
LIST.get(step).set(true);
doSomething(step);
LIST.remove(step);
}
});
}
}
private static void doSomething(int step) {
System.out.println("step: " + step);
}
}
В классе javafx.collections.FXCollections
есть пара статических методов, создающих обертки и отличающихся от других наличием параметра extractor
:
static <E> ObservableList<E> observableArrayList(Callback<E,Observable[]> extractor)
static <E> ObservableList<E> observableList(List<E> list, Callback<E,Observable[]> extractor)
Используя первый метод получаем:
package example;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
public class Main {
private static final ObservableList<BooleanProperty> LIST =
FXCollections.observableArrayList(p -> new Observable[]{p});
public static void main(String[] args) {
LIST.addListener(new ListChangeListener<BooleanProperty>() {
@Override
public void onChanged(Change<? extends BooleanProperty> c) {
while (c.next()) {
// Чтобы посмотреть изменения:
if (c.wasPermutated()) {
for (int i = c.getFrom(); i < c.getTo(); ++i) {
System.out.println("Permuted: " + i + " " + LIST.get(i));
}
} else if (c.wasUpdated()) {
for (int i = c.getFrom(); i < c.getTo(); ++i) {
System.out.println("Updated: " + i + " " + LIST.get(i));
}
} else {
for (BooleanProperty removedItem : c.getRemoved()) {
System.out.println("Removed: " + removedItem);
}
for (BooleanProperty addedItem : c.getAddedSubList()) {
System.out.println("Added: " + addedItem);
}
}
// Полезная нагрузка:
for (int step = c.getFrom(); step < c.getTo(); ++step) {
if (!LIST.get(step).get()) {
LIST.get(step).set(true);
doSomething(step);
LIST.remove(step);
}
}
}
}
});
fillList(3);
change(3);
}
private static void fillList(int count) {
for (int i = 0; i < count; i++) {
// int time = (int) (Math.random() * 10000 + 1000);
// try {
// Thread.sleep(time);
// } catch (InterruptedException ex) {
// Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
// }
LIST.add(new SimpleBooleanProperty(true));
}
}
private static void change(int count) {
for (int i = count - 1; i >= 0; --i) {
// int time = (int) (Math.random() * 10000 + 1000);
// try {
// Thread.sleep(time);
// } catch (InterruptedException ex) {
// Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
// }
switch (i + 1) {
case 1:
LIST.get(i).set(false);
break;
case 2:
LIST.get(i).set(false);
break;
case 3:
LIST.get(i).set(false);
break;
default:
break;
}
}
}
private static void doSomething(int step) {
System.out.println("step: " + step);
}
}
Слушатель устанавливается до внесения изменений (сразу в main()
), так как он в прошлое не может послушать.
Вызовы Thread.sleep()
закомментированны, потому что в этом примере только один поток - хоть сколько жди, а "race condition" не дождешься.
Если я вас правильно понял, то....
Создаем wrapper для коллекции
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import java.util.ArrayList;
import java.util.List;
class BooleanPropertyCollection {
private List<BooleanProperty> listBooleanProperty = new ArrayList<>();
private List<Event> listener = new ArrayList<>();
public void add(SimpleBooleanProperty item) {
listBooleanProperty.add(item);
}
//Публичный лишь для примера, в вашем случае, как я вас понял, он будет private
public void change(int index, boolean newValue) {
listBooleanProperty.set(index, new SimpleBooleanProperty(newValue));
for (Event event: listener) {
event.onChange(this,index);
}
}
public void remove(int index){
listBooleanProperty.remove(index);
}
public int getSize(){
return listBooleanProperty.size();
}
public BooleanProperty getElementByIndex(int index){
return listBooleanProperty.get(index);
}
public void subscribeOnChange(Event event) {
listener.add(event);
}
}
Создадим iterface Event
public interface Event {
public void onChange(BooleanPropertyCollection booleanPropertyCollection, int index);
}
И пример использования:
BooleanPropertyCollection test = new BooleanPropertyCollection();
test.subscribeOnChange((BooleanPropertyCollection booleanPropertyCollection, int index) -> {
System.out.println("Размер до: "+booleanPropertyCollection.getSize());
System.out.println("Изменился элемент index: "+index);
booleanPropertyCollection.remove(index);
System.out.println("Удалили элемент с index: "+index);
System.out.println("Размер после: "+booleanPropertyCollection.getSize());
});
test.add(new SimpleBooleanProperty(false));
test.add(new SimpleBooleanProperty(true));
test.change(1,true);
Как меняется крипторынок и к чему готовиться владельцам криптообменников
Есть код на java awtИз него мне нужна была только "логика"
Люди добрые!) Помогите пожалуйста подключить Bootstrap через @import в СSSСамое интересное Slick-carousel работает а bootstrap нет(( пример на скрине
Привет!Я начал изучать Angular и решил сделать приложение на нем и мне понадобилось подключить шрифты