Juan Ignacio Prez Juan Ignacio Prez - 1 year ago 114
Java Question

JavaFx ViewList shares values thru different instances

Hi StackOverflow people,

First question here, I'm stuck on this code and cannot move forward, tried different approaches but cannot figure out why this is happening.

The code is intended to be a few lists each one represents a day of the week, and each of the list has all the possible time. Now, everytime I ran the code each list, even when not update, is using the last date available. For the sake of the example, remove almost all the lists and leave only 2.

The update on the date is being done on this line, t1.setFecha(lunesDate.plusDays(i));, but if for instance, I remove this line on one of the lists, the list is getting the date updated, even if this is happening on another list, with another variable!! It is like the JVM is considering all the lists to be the same... Makes no sense for me...

Can anyone point where is the issue on the code?

Class Turno.class

import java.time.LocalDate;

import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;

public class Turno {

private static final int LIBRE = 1;
private static final int RESERVADO = 2;
private static final int CUMPLIDO = 3;
private static final int CERRADO = 4;

private SimpleIntegerProperty id = new SimpleIntegerProperty();
private SimpleObjectProperty<LocalDate> fecha = new SimpleObjectProperty<LocalDate>();
private SimpleIntegerProperty idhorario = new SimpleIntegerProperty();
private SimpleStringProperty horario = new SimpleStringProperty();
private SimpleIntegerProperty estado = new SimpleIntegerProperty();
private SimpleIntegerProperty idProfesional = new SimpleIntegerProperty();
private SimpleStringProperty profesional = new SimpleStringProperty();;
private SimpleIntegerProperty idPaciente = new SimpleIntegerProperty();
private SimpleStringProperty paciente = new SimpleStringProperty();;
private SimpleStringProperty observaciones = new SimpleStringProperty();;

public Turno(int id, LocalDate d, int idh, String h, int e, int idpro, String pro, int idpac, String pac,
String o) {
this.setId(id);
this.setFecha(d);
this.setIdHorario(idh);
this.setHorario(h);
this.setEstado(e);
this.setIdProfesional(idpro);
this.setProfesional(pro);
this.setIdPaciente(idpac);
this.setPaciente(pac);
this.setObservaciones(o);
}

public Turno() {
}

// ID
public final SimpleIntegerProperty idProperty() {
return this.id;
}

public final int getId() {
return this.idProperty().get();
}

public final void setId(final int i) {
this.idProperty().set(i);
}

/* Bunch of getter and setters for properties, just like the one above */


Class TestTurno.class

public class TestTurnos extends Application {

private static Turno turnoSeleccionado = null;

ScrollPane scrollPane = new ScrollPane();
HBox listas = new HBox();
VBox vBoxL = new VBox();
VBox vBoxM = new VBox();
ListView<Turno> listViewTurnosL = new ListView<>();
ListView<Turno> listViewTurnosM = new ListView<>();
List<Turno> listaHorarios = new ArrayList<>();
List<Turno> listaTurnos = new ArrayList<>();

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

@Override
public void start(Stage escenario) throws Exception {

// Here we get the current Monday date, in order to prepare for the current week
LocalDate lunesDate = null;
LocalDate diaSemana = null;
LocalDate diaHoy = LocalDate.now();
int d = diaHoy.getDayOfWeek().getValue();
lunesDate = diaHoy.minusDays(d - 1);

// Give the schedules to each day list
listViewTurnosL.setItems(FXCollections.observableList(listaHorarios));
listViewTurnosM.setItems(FXCollections.observableList(listaHorarios));

// Then we look for more data on the DB,
for (int i = 0; i < 2; i++) {
// Database magic happens here, we filled the listaTurnos, not relevant


// We make the lists
//
//!!! Here is where the glitch appears, debugging shows that it only gets into the switch on the right conditions,
// but it keeps on updating the date on any of the lists, even when it is updating another list
switch (i) {
case 0: {
for (Turno t1 : listViewTurnosL.getItems()) {
t1.setFecha(lunesDate.plusDays(i));
}
// Value of t1.getFecha() is 1
break;
}
case 1: {
for (Turno t2 : listViewTurnosM.getItems()) {
t2.setFecha(lunesDate.plusDays(i));
}
// Value of t1.getFecha() is 2 !!!!!
// Value of t2.getFecha() is 2
break;
}
}
}


vBoxL.getChildren().addAll(listViewTurnosL);
vBoxM.getChildren().addAll(listViewTurnosM);

listas.getChildren().addAll(vBoxL, vBoxM);

scrollPane.setContent(listas);
Scene escena = new Scene(scrollPane, 800, 800);
escenario.setScene(escena);
escenario.show();
}
}

Answer Source

Consider how you are creating your lists:

listViewTurnosL.setItems(FXCollections.observableList(listaHorarios));
listViewTurnosM.setItems(FXCollections.observableList(listaHorarios));

The documentation for the factory method you are using reads:

Constructs an ObservableList that is backed by the specified list.

That is - the base list provided is kept as the backing (storing) list. Since both ObservableList instances share the same original ArrayList, it is no wonder they share the content.

You may want to use the factory method FXCollections.ObservableArrayList which creates a new ObservableList (the backing list is created internally, or is the list itself).

If you really need the non-observable list instances, you should probably use two different ones if the lists are not to be equal.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download