JavaFX Warum kriege ich eine Exception?

Diskutiere Warum kriege ich eine Exception? im AWT, Swing, JavaFX & SWT Bereich.
W

White_Fox

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

mihe7

mihe7

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.
 
W

White_Fox

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

mihe7

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).
 
W

White_Fox

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)
 
W

White_Fox

Und die Methode SelectionModel().getFocusedCell() liefert zwar ein plausibles Ergebnis, die Exception kommt aber trotzdem noch. :(
 
W

White_Fox

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. :(
 
W

White_Fox

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);
    }
    
}
 
W

White_Fox

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).
 
M

mrBrown

Kannst du nicht einfach nur den Inhalt der OberveableLists aktualisieren, anstatt die ganze Tabelle neu aufzubauen?
 
W

White_Fox

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.
 
M

mrBrown

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

White_Fox

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.
 
W

White_Fox

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

dzim

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?
 
W

White_Fox

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

dzim

W

White_Fox

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:
W

White_Fox

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.
 
Thema: 

Warum kriege ich eine Exception?

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben