JavaFX actualización fila de la tabla

user3164187:

El escenario que estoy tratando de lograr es,

  1. Cada vez que un particular, TableCellen una TableRowse actualiza, el color de fila será cambiado a rojo y después de 3 segundos, el color debe ser revertido automáticamente a originales.

a continuación es MCVE ,

Clase principal

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public class TestProjectWin10 extends Application {
    private final ObservableList<Element> data = FXCollections.observableArrayList();

    public final Runnable changeValues = () -> {
        int i = 0;
        while (i <= 100000) {
            if (Thread.currentThread().isInterrupted()) {
                break;
            }
            data.get(0).setOccurence(System.currentTimeMillis());
            data.get(0).count();
            i = i + 1;
        }
    };

    private final ExecutorService executor = Executors.newSingleThreadExecutor(runnable -> {
        Thread t = new Thread(runnable);
        t.setDaemon(true);
        return t;
    });

    @Override
    public void start(Stage primaryStage) {

        TableView<Element> table = new TableView<>();
        table.getStylesheets().add(this.getClass().getResource("tableColor.css").toExternalForm());
        table.setEditable(true);

        TableColumn<Element, String> nameCol = new TableColumn<>("Name");
        nameCol.setPrefWidth(200);
        nameCol.setCellValueFactory(cell -> cell.getValue().nameProperty());
        nameCol.setCellFactory((TableColumn<Element, String> param) -> new ColorCounterTableCellRenderer(table));
        table.getColumns().add(nameCol);

        this.data.add(new Element());
        table.setItems(this.data);

        this.executor.submit(this.changeValues);

        Scene scene = new Scene(table, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

La clase de elemento:

import java.util.concurrent.atomic.AtomicReference;

import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Element {
    int x = 0;

    private final StringProperty nameProperty = new SimpleStringProperty("");

    private final AtomicReference<String> name = new AtomicReference<>();

    private final DoubleProperty occurence = new SimpleDoubleProperty();

    public void count() {
        x = x + 1;
        if (name.getAndSet(Integer.toString(x)) == null) {
            Platform.runLater(() -> nameProperty.set(name.getAndSet(null)));
        }
    }

    public void setOccurence(double value) {
        occurence.set(value);
    }

    public String getName() {
        return nameProperty().get();
    }

    public void setName(String name) {
        nameProperty().set(name);
    }

    public StringProperty nameProperty() {
        return nameProperty;
    }

    double getOccurrenceTime() {
        return occurence.get();
    }
}

CellFactory código:

import java.util.Timer;
import java.util.TimerTask;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;

public class ColorCounterTableCellRenderer extends TableCell<Element, String> {

    private final static long MAX_MARKED_TIME = 3000;
    private final static long UPDATE_INTERVAL = 1000;

    private static Timer t = null;
    private final String highlightedStyle = "highlightedRow";

    private final TableView tv;

    public ColorCounterTableCellRenderer(TableView tv) {
        this.tv = tv;
        createTimer();
        setAlignment(Pos.CENTER_RIGHT);
    }

    private void createTimer() {
        if (t == null) {
            t = new Timer("Hightlight", true);
            t.schedule(new TimerTask() {
                @Override
                public void run() {

                    final long currentTime = System.currentTimeMillis();

                    TableRow tr = getTableRow();
                    if (tr.getItem() != null) {

                        if (currentTime - ((Element) tr.getItem()).getOccurrenceTime() > MAX_MARKED_TIME) {
                            Platform.runLater(() -> {
                                tr.getStyleClass().remove(highlightedStyle);
                            });
                        }
                    }
                }
            }, 0, UPDATE_INTERVAL);
        }
    }

    @Override
    protected void updateItem(String item, boolean empty) {
        if (empty || getTableRow() == null || getTableRow().getItem() == null) {
            setText(null);
            return;
        }

        long currentTime = System.currentTimeMillis();

        TableRow<Element> row = getTableRow();
        Element elementRow = row.getItem();

        double occurrenceTime = elementRow.getOccurrenceTime();

        if (currentTime - occurrenceTime < MAX_MARKED_TIME) {
            if (!row.getStyleClass().contains(highlightedStyle)) {
                row.getStyleClass().add(highlightedStyle);
            }
        }

        super.updateItem(item, empty);
        setText(item + "");

    }
}

y la tableColor.css archivo css

.highlightedRow {
    -fx-background-color: rgba(255,0,0, 0.25);
    -fx-background-insets: 0, 1, 2;
    -fx-background: -fx-accent;
    -fx-text-fill: -fx-selection-bar-text;    
}

Cual es el problema..?

  1. Puedo comprobar si la diferencia entre el tiempo y la actualización actual sucedió tiempo es inferior a 3 segundos - color de fila a rojo (en ColorCounterTableCellRenderer- updateItemMétodo)

  2. en un temporizador separado ( ColorCounterTableCellRenderer), trato comprobación de si la diferencia entre el tiempo y la actualización actual ha pasado el tiempo es más de 3 segundos - Extracción de color rojo.

Pero en el temporizador ( createTimer- Método) Código: el tr.getItem()está siempre nully por lo tanto no eliminar el color rojo.

Es esta la forma correcta para lograr lo que quiero? ¿Por qué tr.getItem()vuelve null.

Para la prueba : me encontré con el código y esperó a que executorel código a fin y comprueba si el rojo se retira después de 3 segundos.

Fabian :

Las actualizaciones de la interfaz de usuario, incluso si se activa a través de los oyentes, que hay que hacer desde el subproceso de la aplicación. (Usted puede superar este problema al hacer las actualizaciones usando Platform.runLater.)

Por otra parte no se puede confiar en la misma célula mantener la misma célula por el tiempo completo que se supone debe aparecer en forma marcada.

Para superar este problema que necesita para almacenar la información sobre las células marcadas, ya sea en el propio objeto o de alguna estructura de datos externa observable.

El ejemplo siguiente almacena los tiempos de la última actualización en una ObservableMapy utiliza una AnimationTimerpara borrar entradas caducadas desde el mapa. Además se utiliza TableRows para actualizar un pseudoclass basado en el contenido del mapa.

private static class Item {

    private final IntegerProperty value = new SimpleIntegerProperty();
}

private final ObservableMap<Item, Long> markTimes = FXCollections.observableHashMap();
private AnimationTimer updater;

private void updateValue(Item item, int newValue) {
    int oldValue = item.value.get();
    if (newValue != oldValue) {
        item.value.set(newValue);

        // update time of item being marked
        markTimes.put(item, System.nanoTime());

        // timer for removal of entry
        updater.start();
    }
}

@Override
public void start(Stage primaryStage) {
    Item item = new Item(); // the item that is updated
    TableView<Item> table = new TableView<>();
    table.getItems().add(item);

    // some additional items to make sure scrolling effects can be tested
    IntStream.range(0, 100).mapToObj(i -> new Item()).forEach(table.getItems()::add);

    TableColumn<Item, Number> column = new TableColumn<>();
    column.getStyleClass().add("mark-column");
    column.setCellValueFactory(cd -> cd.getValue().value);
    table.getColumns().add(column);

    final PseudoClass marked = PseudoClass.getPseudoClass("marked");

    table.setRowFactory(tv -> new TableRow<Item>() {

        final InvalidationListener reference = o -> {
            pseudoClassStateChanged(marked, !isEmpty() && markTimes.containsKey(getItem()));
        };
        final WeakInvalidationListener listener = new WeakInvalidationListener(reference);

        @Override
        protected void updateItem(Item item, boolean empty) {
            boolean wasEmpty = isEmpty();
            super.updateItem(item, empty);

            if (empty != wasEmpty) {
                if (empty) {
                    markTimes.removeListener(listener);
                } else {
                    markTimes.addListener(listener);
                }
            }

            reference.invalidated(null);
        }

    });

    Scene scene = new Scene(table);
    scene.getStylesheets().add("style.css");
    primaryStage.setScene(scene);
    primaryStage.show();

    updater = new AnimationTimer() {

        @Override
        public void handle(long now) {
            for (Iterator<Map.Entry<Item, Long>> iter = markTimes.entrySet().iterator(); iter.hasNext();) {
                Map.Entry<Item, Long> entry = iter.next();

                if (now - entry.getValue() > 2_000_000_000L) { // remove after 1 sec
                    iter.remove();
                }
            }

            // pause updates, if there are no entries left
            if (markTimes.isEmpty()) {
                stop();
            }
        }
    };

    final Random random = new Random();

    Thread t = new Thread(() -> {

        while (true) {
            try {
                Thread.sleep(4000);
            } catch (InterruptedException ex) {
                continue;
            }
            Platform.runLater(() -> {
                updateValue(item, random.nextInt(4));
            });
        }
    });
    t.setDaemon(true);
    t.start();
}

style.css

.table-row-cell:marked .table-cell.mark-column {
    -fx-background-color: red;
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=203507&siteId=1
Recomendado
Clasificación