JavaFX Warum kriege ich eine Exception?

White_Fox

Top Contributor
Hallo liebe Leute

Problem in folgender Klasse:
Java:
public class CenterviewStamptable extends SpreadsheetView
        implements
        ModelObservable,
        ListChangeListener<Object>{
    
    private View view;
    private MultiLangSupport lang;
    private ViewSettings settings;
    private StamppageModel activeStamppage;
    private ModelsViewLinkable model;
    private ArrayList<StamptableObservable> selectionobserver;
    
    private Grid centerviewStampgrid;

    public CenterviewStamptable(View view, ModelsViewLinkable model) {
        selectionobserver = new ArrayList<>();
        this.view = view;
        this.model = model;
        lang = new MultiLangSupport();
        settings = ViewSettings.getInstance();
        model.addModelobserver(this, ModelChange.THE_STAMPPAGE_AT_ACTIVE_PAGE_HAS_CHANGED);
        activeStamppage = model.getStamppageModel(model.getAddressOfActiveLibrarypage());
        init();
        //this.addEventHandler(EventType.ROOT, this);
//        eventhandler = new EventHandler<ActionEvent>() {
//            @Override
//            public void handle(ActionEvent event) {
//                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
//            }
//        };
        this.getSelectionModel().getSelectedCells().addListener(this);
    }
    
    private void init(){
        setShowColumnHeader(true);
        setShowRowHeader(false);
        //refreshActiveLibStampPage();
        refreshActiveLibStampPage();
    }
    
    private void refreshActiveLibStampPage() {
        int rowcnt;
        int colcnt;
        int spanwidht;
        int spanstart;
        ObservableList<ObservableList<SpreadsheetCell>> rows;
        
        //Build grid
        rowcnt = activeStamppage.hasNoStampsets() ? 1 : 2 * activeStamppage.cntStampsets();
        colcnt = activeStamppage.hasNoProperties()? 1 : activeStamppage.cntAllProperties();
        centerviewStampgrid = new GridBase(rowcnt, colcnt);
        
        //Build rows
        if(activeStamppage.hasNoStampsets()){
            if (activeStamppage.hasNoProperties()) {    //Im ersten Durchgang wird hier korrekt reingesprungen
                buildEmptyCenterviewStamptableheader();
                rows = getRowWithEmptyMSG();
            }
            else {
                buildCenterviewStamptableheader();
                rows = getRowWithEmptyMSGAndCellspan();
            }
        }
        else{
            if (activeStamppage.hasNoProperties()) {
                buildEmptyCenterviewStamptableheader();
                rows = getRowsWithStampsetNamesAndEmptyMSG();
            }
            else {
                buildCenterviewStamptableheader();
                rows = getRowsWithStampsetNamesAndDescriptions();
            }
        }
        
        this.setGrid(centerviewStampgrid);
        centerviewStampgrid.setRows(rows);
        
        //Build table header
        buildCenterviewStamptableheader();
        
        //Fit Columns
        for(SpreadsheetColumn column : this.getColumns()){
            column.fitColumn();
        }
        
        //span name cells
        if(activeStamppage.hasNoStampsets()){
            spanstart = 0;
            spanwidht = activeStamppage.cntAllProperties();
            centerviewStampgrid.spanColumn(spanwidht, 0, spanstart);
        }
        else{
            spanwidht = activeStamppage.cntPersistantProperties();
            spanstart = activeStamppage.cntTemporaryProperties();
            for (int row = 0; row < rowcnt; row += 2) {
                centerviewStampgrid.spanColumn(spanwidht, row, spanstart);
            }
        }
    }
    
    private void buildEmptyCenterviewStamptableheader() {
        centerviewStampgrid.getColumnHeaders().add(lang.getString(3080));
    }
    
    private void buildCenterviewStamptableheader() {
//        for (StamppageheaderModel stamppageHeader : activeStamppage.getColumnheaderModels()) {
//            if(stamppageHeader.kindOfProperty == KindOfProperty.TEMPORARY){
//                centerviewStampgrid.getColumnHeaders().add(stamppageHeader.propertyName);
//            }
//        }
//        for (StamppageheaderModel stamppageHeader : activeStamppage.getColumnheaderModels()) {
//            if(stamppageHeader.kindOfProperty == KindOfProperty.PERSISTANT){
//                centerviewStampgrid.getColumnHeaders().add(stamppageHeader.propertyName);
//            }
//        }
        for(StamppageheaderModel stamppageHeader : activeStamppage.getColumnheaderModels()){
            centerviewStampgrid.getColumnHeaders().add(stamppageHeader.propertyName);
        }
    }
    
    private ObservableList<ObservableList<SpreadsheetCell>> getRowWithEmptyMSG() {
        ObservableList<ObservableList<SpreadsheetCell>> rows = FXCollections.observableArrayList();
        ObservableList<SpreadsheetCell> row = FXCollections.observableArrayList();
        
        SpreadsheetCell cell = SpreadsheetCellType.STRING.createCell(
                1, 1, 1, 1, lang.getString(3081));
        row.add(cell);
        rows.add(row);
        return rows;
    }
    
    private ObservableList<ObservableList<SpreadsheetCell>> getRowWithEmptyMSGAndCellspan() {
        ObservableList<ObservableList<SpreadsheetCell>> rows = FXCollections.observableArrayList();
        ObservableList<SpreadsheetCell> row = FXCollections.observableArrayList();
        SpreadsheetCell cell;

        for(int colcnt = 0; colcnt < activeStamppage.cntAllProperties(); colcnt++){
            cell = SpreadsheetCellType.STRING.createCell(
                    0, colcnt, 1, 1, lang.getString(3081));
            row.add(cell);
        }
        rows.add(row);
        return rows;
    }

    private ObservableList<ObservableList<SpreadsheetCell>> getRowsWithStampsetNamesAndEmptyMSG() {
        ObservableList<ObservableList<SpreadsheetCell>> rows = FXCollections.observableArrayList();
        ObservableList<SpreadsheetCell> row;
        
        for(int stampsetCnt = 0; stampsetCnt < activeStamppage.cntStampsets(); stampsetCnt++){
            StampsetModel stampset = activeStamppage.getRowModel(stampsetCnt);
            String stampsetName = stampset.getName();
            
            row = getRowWithStampSetName(stampsetName, stampsetCnt);
            rows.add(row);
            
            row = getRowWithEmptyDescriptionMSG(2 * stampsetCnt + 1);
            rows.add(row);
        }
        return rows;
    }

    private ObservableList<ObservableList<SpreadsheetCell>> getRowsWithStampsetNamesAndDescriptions() {
        ObservableList<ObservableList<SpreadsheetCell>> rows = FXCollections.observableArrayList();
        ObservableList<SpreadsheetCell> row;
        
        for(int stampsetCnt = 0; stampsetCnt < activeStamppage.cntStampsets(); stampsetCnt++){
            StampsetModel stampset = activeStamppage.getRowModel(stampsetCnt);
            String stampsetName = stampset.getName();
            
            row = getRowWithStampSetName(stampsetName, stampsetCnt);
            rows.add(row);
            
            row = getRowWithStampDescriptions(stampset.getItemmodels(),2 * stampsetCnt + 1);
            rows.add(row);
        }
        return rows;
    }

    private ObservableList<SpreadsheetCell> getRowWithEmptyDescriptionMSG(int rowcnt) {
        ObservableList<SpreadsheetCell> row = FXCollections.observableArrayList();
        SpreadsheetCell cell;
        
        cell = SpreadsheetCellType.STRING.createCell(rowcnt, 0, 1, 1, lang.getString(3082));
        row.add(cell);
        return row;
    }
    
    private ObservableList<SpreadsheetCell> getRowWithStampSetName(String name, int rowcnt) {
        ObservableList<SpreadsheetCell> row;
        SpreadsheetCell cell;
        int columncnt;
        
        row = FXCollections.observableArrayList();
        if(activeStamppage.hasNoProperties()){
            cell = SpreadsheetCellType.STRING.createCell(rowcnt, 0, 1, 1, name);
            row.add(cell);
        }
        else{
            columncnt = 0;
            for(String s : activeStamppage.getTemporaryProperties()){
                cell = SpreadsheetCellType.STRING.createCell(rowcnt, columncnt, 1, 1, "");
                row.add(cell);
                columncnt++;
            }
            for(String s : activeStamppage.getPersistantProperties()){
                cell = SpreadsheetCellType.STRING.createCell(rowcnt, columncnt, 1, 1, name);
                row.add(cell);
                columncnt++;
            }
        }
        return row;
    }
    
    private ObservableList<SpreadsheetCell> getRowWithStampDescriptions(ArrayList<ComponentstampModel> itemmodels, int rowcnt) {
        ObservableList<SpreadsheetCell> row;
        SpreadsheetCell cell;
        int columnindex;
        String cellcontent;
        
        row = FXCollections.observableArrayList();
        
        columnindex = 0;
        
        for(ComponentstampModel component : itemmodels){
            if(component == null){
                cellcontent = lang.getString(3082);
            }
            else{
                cellcontent = component.getDescription();
            }
            cell = SpreadsheetCellType.STRING.createCell(rowcnt, columnindex, 1, 1, cellcontent);
            row.add(cell);
            columnindex++;
        }
        return row;
    }
    
    /**
     * New StamptableObservers register here.
     *
     * @param observer
     */
    void addStamptableSelectionObserver(StamptableObservable observer){
        if(!selectionobserver.contains(observer)){
            selectionobserver.add(observer);
        }
    }
    
    /**
     * StamptableObserver can remove thereself from notify list here.
     *
     * @param observer
     */
    void removeStamptableSelectionObserver(StamptableObservable observer){
        selectionobserver.remove(observer);
    }
    
    @Override
    public void notifyAboutChanges(ModelChange change) {
        if(change == ModelChange.THE_STAMPPAGE_AT_ACTIVE_PAGE_HAS_CHANGED){
            activeStamppage = model.getStamppageModel(model.getAddressOfActiveLibrarypage());
            refreshActiveLibStampPage();
        }
    }

    @Override
    public void onChanged(Change<? extends Object> c) {
        TablePosition tp;
        int row;
        int column;
        Identifier selectedStampset;
        Identifier selectedProperty;
        
        tp = getSelectionModel().getSelectedCells().get(0);
        System.out.println("Zeile: " + tp.getRow() + " - Spalte: " + tp.getColumn());
        
        row = tp.getRow()/2;
        column = tp.getColumn();
        
        if(activeStamppage.hasNoStampsets()){
            selectedStampset = null;
        }
        else{
            selectedStampset = activeStamppage.getItem(row, column).getRow();
        }
        
        if(activeStamppage.hasNoProperties()){
            selectedProperty = null;
        }
        else{
            selectedProperty = activeStamppage.getItem(row, column).getColumn();
        }
        
        for(StamptableObservable observer : selectionobserver){
            observer.setNewSelection(selectedStampset, selectedProperty);
        }
    }
}

Die Klasse dient dazu, Daten anzuzeigen, soweit, so gut. Wenn ich mein Programm starte und keine Daten vorhanden sind, dann soll die Tabelle eine Zelle mit einer entsprechenden Nachricht anzeigen (siehe refreshActiveLibStampPage-Methode). Das Anzeigen an sich funktioniert soweit.

Jetzt habe ich ein Event, wenn der Benutzer eine Zelle anklickt (onChanged-Methode). Die wird auch korrekt getriggert.

Jetzt kommt das Problem: Wenn ich die Zelle mit der Keine-Daten-Nachricht anklicke, erhalte ich eine IndexOutOfBoundsException. Ich habe den starken Verdacht daß es damit zusammenhängt, daß die SpreadsheetView ein Problem mit den Spalten hat, den tp.column() liefert -1 (siehe onChanged-Methode). Ich sehe aber nicht, welches Problem. Spaltenheader ist da und wird korrekt angezeigt, sowohl SpreadsheetView.getColumns.size() als auch das Grid.getColumnCount() liefern wie erwartet 1. Siehe Screenshot.

Hat jemand eine Idee, woran das liegen kann?
 

Anhänge

  • debug.PNG
    debug.PNG
    89,1 KB · Aufrufe: 66

mihe7

Top Contributor
Hm... Evtl. deswegen:
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TablePosition.html?is-external=true hat gesagt.:
Because the TableView can have different selection modes, the row and column properties in TablePosition can be 'disabled' to represent an entire row or column. This is done by setting the unrequired property to -1 or null.
 

White_Fox

Top Contributor
Hm...ok. Aber mir sagt das leider nicht genug um eine Lösung auszubrüten. Es gibt zwar die Methode getSelectionModel.setSelectionMode(), aber soweit ich das verstehe kann ich da nur auswählen, ob nur eine oder mehrere Zellen gleichzeitig ausgewählt werden können.

Weitere Ideen oder Hinweise?
 

mihe7

Top Contributor
Oh, sorry, das habe ich missverstanden: bei Swing wählt man ja aus, ob man zellen- oder zeilenweise selektieren kann und ich dachte, das bezieht sich darauf (nach dem Motto: bei zeilenweiser Selektion macht die Spalte keinen Sinn).
 

White_Fox

Top Contributor
Wie dumm von mir, ich hätte vielleicht noch den Stacktrace mitliefern können. Und vielleicht kann @dzim ja was damit anfangen...

Code:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException
    at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:136)
    at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:242)
    at com.sun.javafx.scene.control.behavior.TableViewBehaviorBase.lambda$new$219(TableViewBehaviorBase.java:245)
    at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
    at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:75)
    at impl.org.controlsfx.spreadsheet.TableViewSpanSelectionModel.handleSelectedCellsListChangeEvent(TableViewSpanSelectionModel.java:217)
    at impl.org.controlsfx.spreadsheet.TableViewSpanSelectionModel.clearAndSelect(TableViewSpanSelectionModel.java:770)
    at javafx.scene.control.TableView$TableViewSelectionModel.clearAndSelect(TableView.java:1914)
    at com.sun.javafx.scene.control.behavior.TableCellBehaviorBase.simpleSelect(TableCellBehaviorBase.java:215)
    at com.sun.javafx.scene.control.behavior.TableCellBehaviorBase.doSelect(TableCellBehaviorBase.java:148)
    at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:150)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:95)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:431)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    at java.lang.Thread.run(Thread.java:748)
 

White_Fox

Top Contributor
Hm...merkwürdig.

Wenn ich zwei Zellen habe, kann ich zwischen den Zellen hin- und herselektieren ohne daß es zu einer Exception kommt.
Aber wehe ich klicke in den freien Bereich...BUMM. :(
 

White_Fox

Top Contributor
Hm, was ist denn das für ein Müll...da hab ich jetzt ein lauffähiges Minimalbeispiel zusammengestümpert-und nun funktioniert es???

Sieht wenigstens jemand einen Unterschied bei dem, was ich oben gepostet habe?

Java:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TablePosition;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import org.controlsfx.control.spreadsheet.Grid;
import org.controlsfx.control.spreadsheet.GridBase;
import org.controlsfx.control.spreadsheet.SpreadsheetCell;
import org.controlsfx.control.spreadsheet.SpreadsheetCellType;
import org.controlsfx.control.spreadsheet.SpreadsheetView;


public class SpreadsheetViewListening extends Application {
    
    class Table
            extends SpreadsheetView
            implements ListChangeListener<Object>{
        private Grid tablegrid;
        
        public Table() {
            init();
        }
        
        void init(){
            ObservableList<ObservableList<SpreadsheetCell>> rows;
            ObservableList<SpreadsheetCell> row;
            SpreadsheetCell cell;
            
            setShowColumnHeader(true);
            setShowRowHeader(false);
            
            tablegrid = new GridBase(2, 2);
            
            //Build cells
            rows = FXCollections.observableArrayList();
            
            row =  FXCollections.observableArrayList();
            cell = SpreadsheetCellType.STRING.createCell(
                    0, 0, 1, 1, "A1");
            row.add(cell);
            cell = SpreadsheetCellType.STRING.createCell(
                    0, 1, 1, 1, "A2");
            row.add(cell);
            rows.add(row);
            
            row =  FXCollections.observableArrayList();
            cell = SpreadsheetCellType.STRING.createCell(
                    1, 0, 1, 1, "B1");
            row.add(cell);
            cell = SpreadsheetCellType.STRING.createCell(
                    1, 1, 1, 1, "B2");
            row.add(cell);
            rows.add(row);
            
            this.setGrid(tablegrid);
            tablegrid.setRows(rows);
            tablegrid.getColumnHeaders().add("Spalte A");
            tablegrid.getColumnHeaders().add("Spalte B");
            
            //Add Listener
            getSelectionModel().getSelectedCells().addListener(this);
        }

        @Override
        public void onChanged(Change<? extends Object> c) {
            TablePosition tp;
        
            tp = this.getSelectionModel().getFocusedCell();
            System.out.println("Zeile: " + tp.getRow() + " - Spalte: " + tp.getColumn());
        }
    }
    
    @Override
    public void start(Stage primaryStage) {
//        Button btn = new Button();
//        btn.setText("Say 'Hello World'");
//        btn.setOnAction(new EventHandler<ActionEvent>() {
//           
//            @Override
//            public void handle(ActionEvent event) {
//                System.out.println("Hello World!");
//            }
//        });
        
        Table t = new Table();
        StackPane root = new StackPane(t);
//        root.getChildren().add(btn);
        
        Scene scene = new Scene(root, 300, 250);
        
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
    
}
 

White_Fox

Top Contributor
Ich glaube, ich habe den Fehler gefunden.

Im Gegensatz zu dem Beispiel baue ich die Tabelle neu auf. In dem Codebeispiel hab ich den Fehler nachgestellt:
Java:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TablePosition;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import org.controlsfx.control.spreadsheet.Grid;
import org.controlsfx.control.spreadsheet.GridBase;
import org.controlsfx.control.spreadsheet.SpreadsheetCell;
import org.controlsfx.control.spreadsheet.SpreadsheetCellType;
import org.controlsfx.control.spreadsheet.SpreadsheetView;

public class SpreadsheetViewListening extends Application {
    
    class Table
            extends SpreadsheetView
            implements ListChangeListener<Object>{
        private Grid tablegrid;
        
        public Table() {
            init();
            //Add Listener
            getSelectionModel().getSelectedCells().addListener(this);
        }
        
        void init(){
            ObservableList<ObservableList<SpreadsheetCell>> rows;
            ObservableList<SpreadsheetCell> row;
            SpreadsheetCell cell;
            
            setShowColumnHeader(true);
            setShowRowHeader(false);
            
            tablegrid = new GridBase(2, 2);
            
            //Build cells
            rows = FXCollections.observableArrayList();
            
            row =  FXCollections.observableArrayList();
            cell = SpreadsheetCellType.STRING.createCell(
                    0, 0, 1, 1, "A1");
            row.add(cell);
            cell = SpreadsheetCellType.STRING.createCell(
                    0, 1, 1, 1, "A2");
            row.add(cell);
            rows.add(row);
            
            row =  FXCollections.observableArrayList();
            cell = SpreadsheetCellType.STRING.createCell(
                    1, 0, 1, 1, "B1");
            row.add(cell);
            cell = SpreadsheetCellType.STRING.createCell(
                    1, 1, 1, 1, "B2");
            row.add(cell);
            rows.add(row);
            
            this.setGrid(tablegrid);
            tablegrid.setRows(rows);
            tablegrid.getColumnHeaders().add("Spalte A");
            tablegrid.getColumnHeaders().add("Spalte B");
        }

        @Override
        public void onChanged(Change<? extends Object> c) {
            TablePosition tp;
        
            tp = this.getSelectionModel().getFocusedCell();
            System.out.println("Zeile: " + tp.getRow() + " - Spalte: " + tp.getColumn());
            init(); // <- ########## Tabelle neu aufbauen ##########
        }
    }
    
    @Override
    public void start(Stage primaryStage) {
//       
        Table t = new Table();
        StackPane root = new StackPane(t);
//        root.getChildren().add(btn);
        
        Scene scene = new Scene(root, 300, 250);
        
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

In meiner Klasse oben mache ich das, um die Daten aus dem Model zu aktualisieren. Hast du vielleicht eine Idee, wie ich die Tabelle sonst aktualisieren könnte? Den Listener entfernen hab ich schon probiert, aber das klappt nicht (und ich bin mir auch nicht sicher, daß das wirklich ein guter Weg ist).
 

White_Fox

Top Contributor
Hm...mal sehen. Die äußerste Liste könnte ich stehen lassen. Es ist leider ein wesentlicher Bestandteil der ganzen Angelegenheit, Zeilen und Spalten hinzuzufügen und wieder zu entfernen.
 

mrBrown

Super-Moderator
Mitarbeiter
Sind doch auch alles ObservableLists, oder nicht? Einfach leeren und neu füllen sollte klappen, wenn ich grad nicht danebenlieg
 

White_Fox

Top Contributor
Ja, das sind alles ObservableLists. Ich hab gerade mal probiert, die äußere Liste (rows) nur zu leeren und nicht neu zu erstellen. Aber das ändert leider nicht viel, höchstens daß die Exception mal an anderer Stelle kommt.

Ich werde morgen mal ausprobieren was passiert, wenn ich auch die Zeilen-Listen nur leere anstatt sie zu ersetzen. Wobei ich die Lösung recht häßlich fände. Wenn einmal sehr viele Zeilen angezeigt wurden, bleiben halt alle Objekte am Leben, auch wenn sie nicht mehr gebraucht werden.
 

White_Fox

Top Contributor
Sofern niemand eine bessere Idee hat werde ich wohl einen Thread parallel laufen lassen, der so alle 50ms das SelectionModel auswertet und den "Event"kram übernimmt.
Ach man, das ist doch aber eine Scheißlösung...
 

dzim

Top Contributor
Moment'n. Wenn ich den Thread richtig verstehe (und nein, ich hab ihn aufgrund Antworten vorher nur überflogen), willst du @White_Fox eigentlich nur eine Zelle mit einem Platzhalter versehen, wenn noch keine Daten drin sind. Korrekt?
 

White_Fox

Top Contributor
Ja, das war der Plan.
Es kann aber zwischendurch vorkommen, daß später keine Daten mehr da sind (wenn der Benutzer z.B. alle löscht).

Edit:
Wenn es eine andere Möglichkeit für eine leere Ansicht gibt, dann würde ich auch die nehmen, auf die eine leere Zelle will ich mich nicht festlegen. Aber Zeilen/Spalten dynamisch hinzuzufügen und wieder zu entfernen, das wäre schon wichtig (und wenn ich meinen Versuch da oben richtig verstanden habe, ist das das Problem).
 

dzim

Top Contributor
https://controlsfx.bitbucket.io/org...heet/SpreadsheetView.html#placeholderProperty

Analog zu den in JavaFX eingebauten List-, Table- und Tree(Table)View gibt es in der Spreadsheet-API einen Placeholder. Dieser wird angezeigt, wenn keine Daten vorhanden sind. Sollte ein beliebiger Node sein. In der normalen API kommt automatisch so etwas wie ein Label mit dem Inhalt "Keine Daten vorhanden", oder so.
Das kannst du verwenden, um dein Ziel zu erreichen.
 

White_Fox

Top Contributor
Stimmt...ich hab das sogar schon öfter gesehen, daß die Tabelle dann sowas wie "Keine Daten" oder so anzeigt, wenn nichts drin steht. Den Fall 'Keine Daten' kann ich dann streichen.

Edit:
Allerdings ist löst das mein Problem mit der Exception und dem Aktualisieren der Tabelle leider nicht (was mich gerade weitaus mehr stört). :(
 
Zuletzt bearbeitet:

White_Fox

Top Contributor
Ich habe - vorläufig(!) - folgenden Würgaround gebaut, der mir aber schauerliche Abhängigkeiten einbringt:

Java:
class CenterviewContextMenu extends ContextMenu{
    private View view;
    
    //...
    
    @Override
    void show(){
        Identifier rowId = view.getSelectedRowIdentifier();
        //...
    }
}

class CenterviewTable extends SpreadsheetView{
    //...
}

public class View{
    private CenterviewTable table;
    private CenterviewContextMenu contextmenu;
    private Model model;
    
    //...
    
    Identifier getSelectedRowIdentifier(){
        TablePosition tp = table.getSelectionModel.getFocusedCell();
        return model.getRowIdentifier.get(tp.getRow());
    }
}

Die Klasse View, die im Wesentlichen das Hauptfenster bildet, stellt verschiedene package private Methoden zur Verfügung. Damit können alle andere Klassen auf bestimmte Informationen zugreifen. Im Falle des Kontextmenüs werden damit z.B. Items aktiviert oder zur Auswahl deaktiviert.

Ich weiß noch nicht ob ich die Lösung mag. Aber so funktioniert es immerhin erstmal.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Ich kriege eine Fehler Messesage bei meinem Media Player AWT, Swing, JavaFX & SWT 8
H JavaFX Kriege fehler beim Fenster wechseln AWT, Swing, JavaFX & SWT 7
T SWT Wie kriege ich die Position des Textfeldes raus? AWT, Swing, JavaFX & SWT 19
Z kriege kein paint AWT, Swing, JavaFX & SWT 13
A Ich kriege die Grössen einfach nicht auf die Reihe! AWT, Swing, JavaFX & SWT 6
jojoge wie kann ich in eine Benennung eines JButtons eine Variable einbauen? AWT, Swing, JavaFX & SWT 6
MartinNeuerlich Kann mir jemand, der einen Mac mit einem m1 oder m2-Chip hat, eine POM geben mit der Javafx-Fullscreen beim Mac mit m-Chip funktioniert? AWT, Swing, JavaFX & SWT 1
berserkerdq2 Buttons und Shapes sehen ja nach Screengröße klein oder zu groß aus, jemand eine Idee, was man tun kann? AWT, Swing, JavaFX & SWT 1
ExceptionOfExpectation Mit einer laufenden GUI Applikation eine Datei in dem Rechner löschen AWT, Swing, JavaFX & SWT 2
Jose05 Aus einer normalen Java Klasse eine FXML-Klasse laden AWT, Swing, JavaFX & SWT 12
_user_q Gibt es eine Möglichkeit, in Java alle möglichen Zeichen automatisch tippen zu lassen? AWT, Swing, JavaFX & SWT 13
I Einbindung eines jpg/png/icons in eine GUI AWT, Swing, JavaFX & SWT 1
mrbody234 ArrayList<Message> in eine TableView visualisieren AWT, Swing, JavaFX & SWT 2
U Gibt es eine Möglichkeit statt concatenate einen anderen Befehl zu nutzen? AWT, Swing, JavaFX & SWT 9
D Tastaturabfragen CTRL+t, CTRL+E bei eine JTable, bestehend aus JTextAteas AWT, Swing, JavaFX & SWT 4
G JavaFX Wert aus DB lesen, wenn erfolgreich automatisch eine fxml laden, möglich? AWT, Swing, JavaFX & SWT 2
Lukas2904 Wie speicher ich eine Einstellung? AWT, Swing, JavaFX & SWT 1
T Getter und Setter für eine Stage AWT, Swing, JavaFX & SWT 6
P Zwei JTables auf eine A4-Seite mit einstellbaren Rändern AWT, Swing, JavaFX & SWT 9
Monokuma 2D-Grafik Imageimport durch eine gezeichnete Form ersetzen AWT, Swing, JavaFX & SWT 16
M Eine Datei auf den Apache Server hochladen - über das Menü im JavaProgramm AWT, Swing, JavaFX & SWT 7
B JavaFX Warum wird hier eine NullPointer-Exception geworfen? AWT, Swing, JavaFX & SWT 7
VPChief Gibt es eine möglichkeit Dateien aus der jar datei zu kopieren? AWT, Swing, JavaFX & SWT 46
B Swing Sudoku: Laden / Speichern von Zahlen aus/in mehrere JTextFields aus/in eine(r) Textdatei AWT, Swing, JavaFX & SWT 9
P Swing Icon einfügen wirft eine Fehlermeldung AWT, Swing, JavaFX & SWT 3
F Variablen an eine Form binden? AWT, Swing, JavaFX & SWT 2
V Swing für jedes Kästchen eine eigene Farbe AWT, Swing, JavaFX & SWT 2
F Wie bekomme ich den Wert der ComboBox in eine Variable gespeichert welche ich für meinen ActionListener nutzen kann? AWT, Swing, JavaFX & SWT 3
karlmasutra JavaFX Zugriff auf eine erzeugte Scene aus einer anderen Klasse AWT, Swing, JavaFX & SWT 1
Informatiknoob AWT Zahlenraten (eine Zahl zwischen 1 und 10) AWT, Swing, JavaFX & SWT 1
A eine Fehler AWT, Swing, JavaFX & SWT 9
TheJavaKid Auf eine Zeichnung im Canvas reagieren AWT, Swing, JavaFX & SWT 13
A JavaFX Daten in eine HTML-Table mit JS schreiben AWT, Swing, JavaFX & SWT 3
B JavaFX TableView eine Zeile markieren AWT, Swing, JavaFX & SWT 5
J jButton soll nach klicken eine Variable um 1 erhöhen AWT, Swing, JavaFX & SWT 2
J Compiler in der JavaFX stop() Methode warten lassen bist eine Aktion in einer anderen Scene gemacht AWT, Swing, JavaFX & SWT 5
J Swing JavaProgramm für Verschlüssen für eine Datei AWT, Swing, JavaFX & SWT 19
xYurisha JLabel Text einer geöffneten Gui über eine andere Klasse ändern! AWT, Swing, JavaFX & SWT 3
J JavaFX Die Webview stellt eine Webseite nicht dar AWT, Swing, JavaFX & SWT 0
M JavaFX Ein Labeltext eine zeitlang anzeigen dann weiter machen AWT, Swing, JavaFX & SWT 3
F Event wenn Maus eine JList verlässt AWT, Swing, JavaFX & SWT 13
I JAVAFX - Übergabe der Inhalte an eine Scene - Wo ist der Vorteil gegenüber Swing? AWT, Swing, JavaFX & SWT 2
Joker4632 JFrame in eine Runnable auslagern? AWT, Swing, JavaFX & SWT 4
A JScrollPane soll JPanel mit JButtons enthalten und eine Scollbar anzeigen AWT, Swing, JavaFX & SWT 1
B Wie erstelle ich eine JavaFX Anwendung von diesem Code? AWT, Swing, JavaFX & SWT 3
Sanni94 JavaFX Kann man eine Grafik in einen Text einbinden? AWT, Swing, JavaFX & SWT 2
Java_RY AWT Frame in eine eigene klasse auslagern und aufrufen AWT, Swing, JavaFX & SWT 6
I 2D-Grafik Problem beim Ändern der Farbe eine 2d Objekts AWT, Swing, JavaFX & SWT 3
G Eine paint-Methode, 2 Welten? AWT, Swing, JavaFX & SWT 3
Thallius Swing JDatePicker oder Sucht jemand eine Aufgabe? AWT, Swing, JavaFX & SWT 0
K Wie kann ich eine Variable zwischen Tab Klassen weitergeben ? AWT, Swing, JavaFX & SWT 7
D JavaFX Erkennen wenn eine Anwendung geschlossen wird und etwas tun? AWT, Swing, JavaFX & SWT 4
R Swing Durch JComboBox-Item eine TextArea aktualisieren AWT, Swing, JavaFX & SWT 2
M Wie binde ich eine JavaFX ProgressBar an eine Datei Übertragung? AWT, Swing, JavaFX & SWT 2
D Objekte einer Oberfläche in eine Datei/Ordner speichern AWT, Swing, JavaFX & SWT 9
A Mit dem Scene Builder eine Collage erstellen (Bilder beziehen aus Flickr) AWT, Swing, JavaFX & SWT 1
A JFace Wizard: Ist es möglich eine Page zu löschen? AWT, Swing, JavaFX & SWT 2
L Swing Wie programmiere ich eine eigene GUI? AWT, Swing, JavaFX & SWT 12
M Combo Box auswahl in eine Datenbank speichern AWT, Swing, JavaFX & SWT 1
M Swing JTextField getText Mehtode übergeben in eine Klasse zu einer Rechnung AWT, Swing, JavaFX & SWT 1
D AWT Das ganze GUI in eine Klasse? AWT, Swing, JavaFX & SWT 1
J JavaFX eine Art Tabelle, jedoch mit mehreren Zeilen AWT, Swing, JavaFX & SWT 2
L Zwei String Array in eine Spalte einfügen AWT, Swing, JavaFX & SWT 1
U LookAndFeel für eine Komponente AWT, Swing, JavaFX & SWT 2
E Mit Netbeans von einer Form auf eine Komponente einer anderen Form zugreifen AWT, Swing, JavaFX & SWT 2
G Zeichnen auf eine schwergewichtige Komponente? AWT, Swing, JavaFX & SWT 0
S Swing Update eine JTabelle nach einer Drag&Drop Operation AWT, Swing, JavaFX & SWT 0
M Über eine JMenuBar überprüfen ob ein JCheckBoxMenuItem selectiert ist. AWT, Swing, JavaFX & SWT 4
M Wie kann ich eine an Apple Automator angelehnte GUI erstellen? AWT, Swing, JavaFX & SWT 1
A JavaFX Eine Task mit einer ProgressBar verbinden AWT, Swing, JavaFX & SWT 0
S JavaFX Canvas - nur eine Figur auf der Zeichenfläche färben? AWT, Swing, JavaFX & SWT 1
S Swing Mit einem Link eine Methode aufrufen AWT, Swing, JavaFX & SWT 2
C Swing Durch Inhaltsänderung eines JTextfields eine Funktion aufrufen AWT, Swing, JavaFX & SWT 5
G 2D-Slider bzw. eine graphische Auswahlkomponente die sich so verhält AWT, Swing, JavaFX & SWT 6
H Lust auf eine Open-Source Lösung für universelle Java Client-Technologie? AWT, Swing, JavaFX & SWT 11
T Aus JAVA.Jar GUI eine Flash-Datei machen AWT, Swing, JavaFX & SWT 3
S 5 Playlisten eine Skip() AWT, Swing, JavaFX & SWT 4
M SWT Browser nur eine Seite erlauben AWT, Swing, JavaFX & SWT 3
B Daten in eine JTable schreiben AWT, Swing, JavaFX & SWT 3
K GUI Elemente über eine separate Textdatei beschriften? AWT, Swing, JavaFX & SWT 4
G noch eine Frage zum EventDispachThread AWT, Swing, JavaFX & SWT 4
I Anhand ButtonGroup eine Auswahl treffen AWT, Swing, JavaFX & SWT 2
B Nach dem Öffnen des Dialogs eine Aktion ausführen. AWT, Swing, JavaFX & SWT 6
W Funktion aus einer Java Datei in eine andere einbauen AWT, Swing, JavaFX & SWT 25
A Swing Text auf eine Seite an beliebigen Orten schreiben AWT, Swing, JavaFX & SWT 6
G Swing Value von einer JScrollBar auf eine andere übertragen AWT, Swing, JavaFX & SWT 2
Rudolf Swing Wie testet man am besten eine GUI? AWT, Swing, JavaFX & SWT 3
P Swing Alle Zeilen einer Spalte (jTable) zusammen zählen und in eine eigene Zeile das Ergebnis schreiben. AWT, Swing, JavaFX & SWT 7
F GroupableTableHeader zeigt nur eine Zeile AWT, Swing, JavaFX & SWT 4
N Swing Optimale Höhe eine JTextPanes bei festgelegter Breite bestimmen AWT, Swing, JavaFX & SWT 23
R Swing Mit Swing eine throws Exception Methode öffnen AWT, Swing, JavaFX & SWT 3
M Eine Kugel nach rechts bewegen AWT, Swing, JavaFX & SWT 5
C Swing NullPointerException beim Hinzufügen von Checkboxes in eine ArrayList AWT, Swing, JavaFX & SWT 5
GUI-Programmer LayoutManager Kurze Layout Frage - eine komponente mittig? AWT, Swing, JavaFX & SWT 5
lumo SWT Zeichnen bescheunigen bzw eine allg. Frage AWT, Swing, JavaFX & SWT 8
M Auf einem Bild eine Markierung aufziehen AWT, Swing, JavaFX & SWT 3
R Eine Instanz von JPanel mehrfach hinzufügen AWT, Swing, JavaFX & SWT 2
B eine .jar erzeugen AWT, Swing, JavaFX & SWT 4
M In JField eine Kommazahl darstellen java.lang.NumberFormatException AWT, Swing, JavaFX & SWT 4
N Button on click eine andere Klasse aufrufen... AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben