JavaFX TableView mit Zeilenumbruch in Zellen

eldrior

Aktives Mitglied
Hallo,

ich habe in meiner Anwendung mit JavaFX (FXML) eine Tabelle. Diese Tabelle wird mit Text gefüllt, der teilweise länger ist, als die Zelle breit, daher möchte ich gerne einen automatischen Zeilenumbruch haben.
Ich habe gelesen, dass ich dafür meine eigene CellFactory brauche und habe mithilfe von Google folgende Klasse geschrieben:

Java:
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.text.Text;
import javafx.util.converter.DefaultStringConverter;

public class WrappingTextFieldTableCell<S> extends TextFieldTableCell<S, String>
{

    private final Text cellText;

    public WrappingTextFieldTableCell() {
        super(new DefaultStringConverter());
        this.cellText = createText();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setGraphic(cellText);
    }

    @Override
    public void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        if (!isEmpty() && !isEditing()) {
            setGraphic(cellText);
        }
    }

    private Text createText() {
        Text text = new Text();
        text.wrappingWidthProperty().bind(widthProperty());
        text.textProperty().bind(itemProperty());
        return text;
    }
}

Ich habe in meinem Controller eine Methode, in der ich folgendes versuche:

Java:
    private void setUpTable ()
    {
        tc1.setCellFactory(param -> new WrappingTextFieldTableCell<EmpWeekOvw>());

        tc1.setCellValueFactory(new PropertyValueFactory<>("week1"));
    }

tc1:
Java:
@FXML
    private TableColumn<EmpWeekOvw, String> tc1;

Ich bekomme in der WrappingTextFieldTableCell Klasse jetzt aber folgenden Error, wenn ich versuche die Anwendung zu starten:

Code:
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$156(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: de.mycompany.wochenplan.domain.WeekText cannot be cast to java.lang.String
    at de.mycompany.wochenplan.gui.controller.weekOvwPopup.WrappingTextFieldTableCell.updateItem(WrappingTextFieldTableCell.java:7)
    at javafx.scene.control.TableCell.updateItem(TableCell.java:663)
    at javafx.scene.control.TableCell.indexChanged(TableCell.java:468)
    at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
    at com.sun.javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:533)
    at com.sun.javafx.scene.control.skin.TableRowSkinBase.init(TableRowSkinBase.java:147)
    at com.sun.javafx.scene.control.skin.TableRowSkin.<init>(TableRowSkin.java:64)
    at javafx.scene.control.TableRow.createDefaultSkin(TableRow.java:212)
    at javafx.scene.control.Control.impl_processCSS(Control.java:859)
    at javafx.scene.Node.processCSS(Node.java:9056)
    at javafx.scene.Node.applyCss(Node.java:9153)
    at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1964)
    at com.sun.javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1797)
    at com.sun.javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1879)
    at com.sun.javafx.scene.control.skin.VirtualFlow.computeViewportOffset(VirtualFlow.java:2528)
    at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1189)
    at javafx.scene.Parent.layout(Parent.java:1079)
    at javafx.scene.Parent.layout(Parent.java:1085)
    at javafx.scene.Parent.layout(Parent.java:1085)
    at javafx.scene.Parent.layout(Parent.java:1085)
    at javafx.scene.Parent.layout(Parent.java:1085)
    at javafx.scene.Group.prefWidth(Group.java:182)
    at javafx.scene.Scene.getPreferredWidth(Scene.java:1697)
    at javafx.scene.Scene.resizeRootToPreferredSize(Scene.java:1673)
    at javafx.scene.Scene.preferredSize(Scene.java:1645)
    at javafx.scene.Scene.impl_preferredSize(Scene.java:1720)
    at javafx.stage.Window$9.invalidated(Window.java:846)
    at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:109)
    at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:144)
    at javafx.stage.Window.setShowing(Window.java:922)
    at javafx.stage.Window.show(Window.java:937)
    at javafx.stage.Stage.show(Stage.java:259)
    at de.mycompany.wochenplan.gui.ScreenFramework.<init>(ScreenFramework.java:36)
    at de.mycompany.wochenplan.Main.start(Main.java:42)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$163(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$176(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$174(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$175(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
Exception running application de.mycompany.wochenplan.Main
TL;DR: WeekText cannot be cast to java.lang.String

Ich vermute mal, dass ich da irgendwas noch nicht ganz richtig verstanden habe, daher wäre es nett, wenn mir hier jemand auf die Sprünge helfen könnte. Falls ihr einfachere Möglichkeiten kennt, wie man dafür sorgt, dass Text in Zellen automatisch umbricht (ohne Scrollbar --> Höhe der Zeile einfach anpassen), wäre ich dafür natürlich auch dankbar.


Vielen Dank im Voraus
eldrior
 
Genau, "week1" ist einfach ein WeekText und in EmpWeekOvw sind aktuell ein paar WeekText's gespeichert, die pro Zeile auf die einzelnen Spalten verteilt werden sollen. Eine ToString ist implementiert und alle Getter/Setter sind vorhanden.
Die Klasse WeekText ist eine Entity, ich habe zusätzlich die toString implementiert.

Wir können um das zu vereinfachen aber auch jede andere Klasse nehmen, in der ein String gespeichert ist...
 
Deine Cells hast du als eine Cells mit Strings als Inhalt deklariert - nutzen tust du sie aber für WeekText, das gibt ja auch die CellValueFactory zurück 😉

Deine Cell kannst du as TableCell<S,WeekItem> deklarieren, das dürfte in dem Fall passender sein
 
Ist wahrscheinlich nicht die sauberste Lösung, aber ich habe in meiner EmpWeekOvw jetzt die Getter so implementiert, dass Strings zurück kommen. Dann kann ich den restlichen Code (fast) komplett so nutzen und es funktioniert.
Wenn ich die TableCell so implementiert hätte, wie du es vorgeschlagen hast, hätte meine WrappingTextFieldTableCell nicht mehr funktioniert (bspw. new DefaultStringConverter()).

Der Workaround funktioniert jetzt erstmal. Ich werde mich demnächst mal näher damit beschäftigen, wie genau die WrappingTextFieldTableCell funktioniert, sodass ich das sauber implementieren kann (oder hat da jemand einen Tipp? 🙂).

Vielen Dank für deine Hilfe!
 

Zurück
Oben