TableView Zeilen einfärben

Tintenfisch

Bekanntes Mitglied
Hey,
folgendes Problem, ich möchte in einer TableView bestimmte Zeilen farblich hervorheben. Es gibt zwar zahlreiche Internetbeispiele, aber diese funktional auf meine Anwendung zu übertragen, gelingt nicht. Ich wäre sehr dankbar, wenn dort jemand eine Lösung zu hätte.
Folgend mal der bisherige Code zur Orientierung:
Java:
            TableView <Date> mainCalendarTable = new TableView<>();
            mainCalendarTable.prefHeightProperty().bind(primaryStage.heightProperty());
            mainCalendarTable.prefWidthProperty().bind(primaryStage.widthProperty());
            mainCalendarTable.setEditable(false);
            
            TableColumn <Date, String> dateColumn = new TableColumn<>("DATE");
            dateColumn.setCellValueFactory(new PropertyValueFactory <> ("date"));
            dateColumn.setCellFactory(TextFieldTableCell.forTableColumn());
            dateColumn.setSortable(false);
            
            TableColumn <Date, String> user1Column = new TableColumn<>("USER_1");
            user1Column.setCellValueFactory(new PropertyValueFactory <> ("user1"));
            user1Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user1Column.setPrefWidth(100.0);
            user1Column.setVisible(true);
            user1Column.setSortable(false);
            
            TableColumn <Date, String> user2Column = new TableColumn<>("USER_2");
            user2Column.setCellValueFactory(new PropertyValueFactory <> ("user3"));
            user2Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user2Column.setPrefWidth(100.0);
            user2Column.setVisible(true);
            user2Column.setSortable(false);
            
            TableColumn <Date, String> user3Column = new TableColumn<>("USER_3");
            user3Column.setCellValueFactory(new PropertyValueFactory <> ("user3"));
            user3Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user3Column.setPrefWidth(100.0);
            user3Column.setVisible(true);
            user3Column.setSortable(false);
        
            mainCalendarTable.getColumns().addAll(dateColumn, user1Column, user2Column, user3Column);
            mainCalendarTable.setItems(getDate(user1));
            
            mainCenter.getChildren().add(mainCalendarTable);
            main.setCenter(mainCenter);
            
            editableAll.setOnAction(new EventHandler <ActionEvent>() {
                @Override
                public void handle(ActionEvent arg0) {
                    if (mainCalendarTable.isEditable() == false) {
                    mainCalendarTable.setEditable(true);
                    } else {
                        mainCalendarTable.setEditable(false);
                    }
                }
            });
            Scene mainScene = new Scene(main,400,400);
            mainScene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(mainScene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    private ObservableList<Date> getDate(User user1) {
        ObservableList <Date> dateList = FXCollections.observableArrayList();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd LLLL yyy");
        int i = 0;
        for (LocalDate date : dateList()) {
        dateList.add(new Date(date.format(formatter), user1.getEntry()[i]));
        i ++;
        }
        return dateList;
    }
    public List<LocalDate> dateList () {
        LocalDate startDate = LocalDate.of(2020, 01, 01);
        LocalDate endDate = LocalDate.of(2020, 12, 31);
        List<LocalDate> dateList = dateFormTo(startDate, endDate);
        return dateList;
    }
    private List<LocalDate> dateFormTo(LocalDate startDate, LocalDate endDate) {
        return startDate.datesUntil(endDate)
                .collect(Collectors.toList());
    }
    public static void main(String[] args) {
        launch(args);
    }
}
 
Hey,
folgendes Problem, ich möchte in einer TableView bestimmte Zeilen farblich hervorheben. Es gibt zwar zahlreiche Internetbeispiele, aber diese funktional auf meine Anwendung zu übertragen, gelingt nicht. Ich wäre sehr dankbar, wenn dort jemand eine Lösung zu hätte.
Folgend mal der bisherige Code zur Orientierung:
Java:
            TableView <Date> mainCalendarTable = new TableView<>();
            mainCalendarTable.prefHeightProperty().bind(primaryStage.heightProperty());
            mainCalendarTable.prefWidthProperty().bind(primaryStage.widthProperty());
            mainCalendarTable.setEditable(false);
           
            TableColumn <Date, String> dateColumn = new TableColumn<>("DATE");
            dateColumn.setCellValueFactory(new PropertyValueFactory <> ("date"));
            dateColumn.setCellFactory(TextFieldTableCell.forTableColumn());
            dateColumn.setSortable(false);
           
            TableColumn <Date, String> user1Column = new TableColumn<>("USER_1");
            user1Column.setCellValueFactory(new PropertyValueFactory <> ("user1"));
            user1Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user1Column.setPrefWidth(100.0);
            user1Column.setVisible(true);
            user1Column.setSortable(false);
           
            TableColumn <Date, String> user2Column = new TableColumn<>("USER_2");
            user2Column.setCellValueFactory(new PropertyValueFactory <> ("user3"));
            user2Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user2Column.setPrefWidth(100.0);
            user2Column.setVisible(true);
            user2Column.setSortable(false);
           
            TableColumn <Date, String> user3Column = new TableColumn<>("USER_3");
            user3Column.setCellValueFactory(new PropertyValueFactory <> ("user3"));
            user3Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user3Column.setPrefWidth(100.0);
            user3Column.setVisible(true);
            user3Column.setSortable(false);
       
            mainCalendarTable.getColumns().addAll(dateColumn, user1Column, user2Column, user3Column);
            mainCalendarTable.setItems(getDate(user1));
           
            mainCenter.getChildren().add(mainCalendarTable);
            main.setCenter(mainCenter);
           
            editableAll.setOnAction(new EventHandler <ActionEvent>() {
                @Override
                public void handle(ActionEvent arg0) {
                    if (mainCalendarTable.isEditable() == false) {
                    mainCalendarTable.setEditable(true);
                    } else {
                        mainCalendarTable.setEditable(false);
                    }
                }
            });
            Scene mainScene = new Scene(main,400,400);
            mainScene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(mainScene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    private ObservableList<Date> getDate(User user1) {
        ObservableList <Date> dateList = FXCollections.observableArrayList();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd LLLL yyy");
        int i = 0;
        for (LocalDate date : dateList()) {
        dateList.add(new Date(date.format(formatter), user1.getEntry()[i]));
        i ++;
        }
        return dateList;
    }
    public List<LocalDate> dateList () {
        LocalDate startDate = LocalDate.of(2020, 01, 01);
        LocalDate endDate = LocalDate.of(2020, 12, 31);
        List<LocalDate> dateList = dateFormTo(startDate, endDate);
        return dateList;
    }
    private List<LocalDate> dateFormTo(LocalDate startDate, LocalDate endDate) {
        return startDate.datesUntil(endDate)
                .collect(Collectors.toList());
    }
    public static void main(String[] args) {
        launch(args);
    }
}
Zu dem Thema hattest du doch schon eine Thread geöffnet.

Sag uns doch welche Zeile du farblich hervorheben willst. Hier und im letzten Thread sagtest du nur bestimmte.
 
Ich sage nur CellFactory und PseudoClass. Das ist der Weg den ich persönlich in solchen Fällen verwende. Und im folgenden StackOverflow wird noch die Dampfhammer-Methode via #setStyle gezeigt.
Eigentlich ist das sehr einfach zu finden im WWW...

Und wie @lam_tr sagt: warum machst du mehrere Threads zum selben Thema?
 
Ich sage nur CellFactory und PseudoClass. Das ist der Weg den ich persönlich in solchen Fällen verwende. Und im folgenden StackOverflow wird noch die Dampfhammer-Methode via #setStyle gezeigt.
Eigentlich ist das sehr einfach zu finden im WWW...

Und wie @lam_tr sagt: warum machst du mehrere Threads zum selben Thema?
Danke für die Antwort. Ich bin es nun mit folgender Methode angegangen. Eingefärbt werden die Zeilen, nur was mir merkwürdig erscheint, die Zeilen färben sich erst, wenn ich ein wenig in der GUI hoch und runter scrolle. Zuerst werden nur die Samstage und Sonntage, wie auch gewünscht eingefärbt, doch so mehr ich scrolle, färben sich auch die anderen Tage, bis schließlich alles gelb ist.
Vielleicht siehst du dort ja den Fehler, ich kann es mir irgendwie nicht erklären, wäre auf jeden Fall dankbar darüber =)
Mehrere Threads? Muss sich sicher um einen Fehler handeln, ist eigentlich der einzige zu diesem Thema gewesen gewesen 🤔
Java:
    mainCalendarTable.setRowFactory(row -> new TableRow<Date>() {
            @Override
            public void updateItem (Date item, boolean empty) {
                
                super.updateItem(item, empty);
                
                if (item == null || empty) {
                    setStyle("");
                } else {
                    if (item.getDayOfWeek().equals("SATURDAY") || item.getDayOfWeek().equals("SUNDAY")) {
                        for (int i = 0; i < getChildren().size(); i += 2) {
                            ((Labeled) getChildren().get(i)).setStyle("-fx-background-color: yellow");
                        }
                    } else {
                        if (getTableView().getSelectionModel().getSelectedItems().contains(item)) {
                            for (int i = 0; i < getChildren().size(); i ++) {
                                ((Labeled) getChildren().get(i)).setTextFill(Color.WHITE);;
                            }
                        } else {
                            for (int i = 0; i < getChildren().size(); i ++) {
                                ((Labeled) getChildren().get(i)).setTextFill(Color.BLUE);;
                            }
                        }
                    }
                }
            }
            });
 
Also ich habe das ganze jetzt mit einem etwas ausgedünnten Konstrukt realisiert. Merkwürdig ist nur, dass sobald ich das ganze über eine Schleife realisieren will, muss ich die hervorgehobenen Felder quasi erst mit dem hoch und runter scrollen aktivieren🤷‍♂️

[CODE lang="java" title="ohne Schleife"] mainCalendarTable.setRowFactory(row -> new TableRow<Date>() {
@Override
public void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
if (item == null || item.getDayOfWeek().equals(null))
setStyle("");
else if (item.getDayOfWeek().equals("SUNDAY") || item.getDayOfWeek().equals("SATURDAY"))
setStyle("-fx-background-color: blue;");
else
setStyle("");
}
});[/CODE]

[CODE lang="java" title="mit Schleife"]mainCalendarTable.setRowFactory(row -> new TableRow<Date>() {
@Override
public void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
if (item == null || item.getDayOfWeek().equals(null))
setStyle("");
else if (item.getDayOfWeek().equals("SUNDAY") || item.getDayOfWeek().equals("SATURDAY")) {
for (int i = 0; i < getChildren().size(); i ++) {
setStyle("-fx-background-color: blue;");
}
}
else
setStyle("");
}
});[/CODE]
 
Also ich habe das ganze jetzt mit einem etwas ausgedünnten Konstrukt realisiert. Merkwürdig ist nur, dass sobald ich das ganze über eine Schleife realisieren will, muss ich die hervorgehobenen Felder quasi erst mit dem hoch und runter scrollen aktivieren🤷‍♂️

[CODE lang="java" title="ohne Schleife"] mainCalendarTable.setRowFactory(row -> new TableRow<Date>() {
@Override
public void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
if (item == null || item.getDayOfWeek().equals(null))
setStyle("");
else if (item.getDayOfWeek().equals("SUNDAY") || item.getDayOfWeek().equals("SATURDAY"))
setStyle("-fx-background-color: blue;");
else
setStyle("");
}
});[/CODE]

[CODE lang="java" title="mit Schleife"]mainCalendarTable.setRowFactory(row -> new TableRow<Date>() {
@Override
public void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
if (item == null || item.getDayOfWeek().equals(null))
setStyle("");
else if (item.getDayOfWeek().equals("SUNDAY") || item.getDayOfWeek().equals("SATURDAY")) {
for (int i = 0; i < getChildren().size(); i ++) {
setStyle("-fx-background-color: blue;");
}
}
else
setStyle("");
}
});[/CODE]
Also meine Annahme ist, wenn du schon die Kinder einer Row den Style setzt, dann muss du beim Reseten auch die Kinder zurücksetzen

Hier ist das Setzen:
Java:
for (int i = 0; i < getChildren().size(); i += 2) {
    ((Labeled) getChildren().get(i)).setStyle("-fx-background-color: yellow");
}

Hier das Reseten:
Java:
 if (item == null || item.getDayOfWeek().equals(null)){
     
for (int i = 0; i < getChildren().size(); i += 2) {
    ((Labeled) getChildren().get(i)).setStyle(null);
}
}
 
Hey,
folgendes Problem, ich möchte in einer TableView bestimmte Zeilen farblich hervorheben. Es gibt zwar zahlreiche Internetbeispiele, aber diese funktional auf meine Anwendung zu übertragen, gelingt nicht. Ich wäre sehr dankbar, wenn dort jemand eine Lösung zu hätte.
Folgend mal der bisherige Code zur Orientierung:
Java:
            TableView <Date> mainCalendarTable = new TableView<>();
            mainCalendarTable.prefHeightProperty().bind(primaryStage.heightProperty());
            mainCalendarTable.prefWidthProperty().bind(primaryStage.widthProperty());
            mainCalendarTable.setEditable(false);
          
            TableColumn <Date, String> dateColumn = new TableColumn<>("DATE");
            dateColumn.setCellValueFactory(new PropertyValueFactory <> ("date"));
            dateColumn.setCellFactory(TextFieldTableCell.forTableColumn());
            dateColumn.setSortable(false);
          
            TableColumn <Date, String> user1Column = new TableColumn<>("USER_1");
            user1Column.setCellValueFactory(new PropertyValueFactory <> ("user1"));
            user1Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user1Column.setPrefWidth(100.0);
            user1Column.setVisible(true);
            user1Column.setSortable(false);
          
            TableColumn <Date, String> user2Column = new TableColumn<>("USER_2");
            user2Column.setCellValueFactory(new PropertyValueFactory <> ("user3"));
            user2Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user2Column.setPrefWidth(100.0);
            user2Column.setVisible(true);
            user2Column.setSortable(false);
          
            TableColumn <Date, String> user3Column = new TableColumn<>("USER_3");
            user3Column.setCellValueFactory(new PropertyValueFactory <> ("user3"));
            user3Column.setCellFactory(TextFieldTableCell.forTableColumn());
            user3Column.setPrefWidth(100.0);
            user3Column.setVisible(true);
            user3Column.setSortable(false);
      
            mainCalendarTable.getColumns().addAll(dateColumn, user1Column, user2Column, user3Column);
            mainCalendarTable.setItems(getDate(user1));
          
            mainCenter.getChildren().add(mainCalendarTable);
            main.setCenter(mainCenter);
          
            editableAll.setOnAction(new EventHandler <ActionEvent>() {
                @Override
                public void handle(ActionEvent arg0) {
                    if (mainCalendarTable.isEditable() == false) {
                    mainCalendarTable.setEditable(true);
                    } else {
                        mainCalendarTable.setEditable(false);
                    }
                }
            });
            Scene mainScene = new Scene(main,400,400);
            mainScene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(mainScene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    private ObservableList<Date> getDate(User user1) {
        ObservableList <Date> dateList = FXCollections.observableArrayList();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd LLLL yyy");
        int i = 0;
        for (LocalDate date : dateList()) {
        dateList.add(new Date(date.format(formatter), user1.getEntry()[i]));
        i ++;
        }
        return dateList;
    }
    public List<LocalDate> dateList () {
        LocalDate startDate = LocalDate.of(2020, 01, 01);
        LocalDate endDate = LocalDate.of(2020, 12, 31);
        List<LocalDate> dateList = dateFormTo(startDate, endDate);
        return dateList;
    }
    private List<LocalDate> dateFormTo(LocalDate startDate, LocalDate endDate) {
        return startDate.datesUntil(endDate)
                .collect(Collectors.toList());
    }
    public static void main(String[] args) {
        launch(args);
    }
}
JavaFX [61] - CSS - Einstieg in CSS - YouTube der erklärt wie es mit css geht
du kannst das natürlich auch mit hover und anderen properties machen


die einbindung da hat er auch ein video dazu gemacht
 
Erst mal: Warum das erst beim Scrollen klappt könnte an dem "virtual flow"-Model der Liste/Tabelle liegen. Es werden ja immer nur die Zellen geladen (oder aktualisiert), die gerade im ViewPort - also sichtbar - sind.

Aber: Ich verstehe die Logik nicht. Wenn ein Item ein WE-Tag ist, färbst du einfach alles gelb oder nicht - da wird also ständig etwas eingefärbt und entfärbt... Das ergibt keinen Sinn.

Aus dem Gedächtnis heraus würde ich es wohl so machen:
Java:
mainCalendarTable.setRowFactory(row -> new TableRow<Date>() {
    @Override
    public void updateItem(Date item, boolean empty) {
        super.updateItem(item, empty);
        TableRow<CallLogs> currentRow = getTableRow();
        if (item == null || item.getDayOfWeek().equals(null)) {
            setCustomStyle(false);
        } else if (item.getDayOfWeek().equals("SUNDAY") || item.getDayOfWeek().equals("SATURDAY")) {
            setCustomStyle(true);
        } else {
            setCustomStyle(false);
        }
    }
    
    public void setCustomStyle(boolean set) {
        TableRow<CallLogs> currentRow = getTableRow();
        currentRow.setStyle(set ? "-fx-background-color: blue;" : ""); // oder null statt ""
    }
});
So würde ich es jedenfalls mal Anhand des oben von mir verlinkten StackOverflow mal probieren. Hast du das überhaupt angeschaut?
 
nur was mir merkwürdig erscheint, die Zeilen färben sich erst, wenn ich ein wenig in der GUI hoch und runter scrolle.
ich hatte ein ähnliches Problem, dabei haben sich beim Scrollen ungewollt immer mehr Zeilen eingefärbt.
Ein TableView.refesh(); hat geholfen.

Java:
        dbFahrerListeTV.setRowFactory(new Callback<TableView<Fahrer>, TableRow<Fahrer>>() {
            @Override
            public TableRow<Fahrer> call(TableView<Fahrer> paramP) {              
                return new TableRow<Fahrer>() {
                    @Override
                    protected void updateItem(Fahrer paramT, boolean paramBoolean) {
                        super.updateItem(paramT, paramBoolean);
                       
                        if (paramT != null)    {
                            if (paramT.isFahrerChoosed()) {
                                setStyle("-fx-background-color: #BDBDBD");
                                dbFahrerListeTV.refresh();
                                         
                            }
                        }                      
                    }
                };
            }
        });
 
Zuletzt bearbeitet:
ich hatte ein ähnliches Problem, dabei haben sich beim Scrollen ungewollt immer mehr Zeilen eingefärbt.
Ein TableView.refesh(); hat geholfen.

Java:
        dbFahrerListeTV.setRowFactory(new Callback<TableView<Fahrer>, TableRow<Fahrer>>() {
            @Override
            public TableRow<Fahrer> call(TableView<Fahrer> paramP) {             
                return new TableRow<Fahrer>() {
                    @Override
                    protected void updateItem(Fahrer paramT, boolean paramBoolean) {
                        super.updateItem(paramT, paramBoolean);
                      
                        if (paramT != null)    {
                            if (paramT.isFahrerChoosed()) {
                                setStyle("-fx-background-color: #BDBDBD");
                                dbFahrerListeTV.refresh();
                                        
                            }
                        }                     
                    }
                };
            }
        });
Du muss eben, wenn der item == null oder empty ist den Style zurücksetzen.
 
Ja cool, vielen Dank für die zahlreichen Antworten. Das mit dem TableView.refresh() hat schon gut funktioniert. Angewandt wurde des weiteren CSS. Folgend nun die aktuelle Lösung, welche mir für dieses Ergebnis am praktikabelsten erschien.

Java:
mainCalendarTable.setRowFactory(row -> new TableRow<Date>() {
                @Override
                public void updateItem(Date item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item == null || item.getDayOfWeek().equals(null)) {
                        this.setId("not-weekend");
                    }
                    else if (item.getDayOfWeek().equals("SUNDAY") || item.getDayOfWeek().equals("SATURDAY")) {
                        getStyleClass().add("weekend-row");
                        mainCalendarTable.refresh();
                    }
                    else {
                        getStyleClass().add("not-weekend");
                        mainCalendarTable.refresh();
                        }
                }
            });
 
Also ich hab auch schon per Zeile oder Zelle CSS-Styles gebraucht. Ein kompletter refresh der Tabelle war nie nötig. Beobachtet zur Sicherheit mal, ob ihr etwas wegen der Performance merkt (Ruckler, etc.). Wenn nicht: Gut. Wenn doch: Zurück an den Code.
¯\_(ツ)_/¯
 
Also ich hab auch schon per Zeile oder Zelle CSS-Styles gebraucht. Ein kompletter refresh der Tabelle war nie nötig. Beobachtet zur Sicherheit mal, ob ihr etwas wegen der Performance merkt (Ruckler, etc.). Wenn nicht: Gut. Wenn doch: Zurück an den Code.
¯\_(ツ)_/¯
Ja stimmt, diese Anmerkung wollte ich auch noch machen. Direktes refresh hatte bisher auch nicht gemacht, wäre auch nervig wenn ich bei jede Modelländerung ein erzwingtes Update des Controls aufrufen muss.
 

Zurück
Oben