JavaFX Etwas Tabellenartiges + Cell-Content-Changed-Event (o.ä.)

White_Fox

Top Contributor
Hallo allerseits

Ich will dem Benutzer eine Tabelle (bisher meist SpreadsheetView, ich bin darauf allerdings nicht festgelegt, Zellen verbinden u.ä. Späße brauche ich nicht) präsentieren und brauche ein Event, wenn sich der Inhalt einer Zelle geändert hat. Allerdings
a)
finde ich keine Event-Klasse die für mein Problem geeignet scheint
b)
kriege ich selbst sowas wie Mouse-Clicked-Events nicht angestoßen.

Hat jemand eine Idee?
Ich brauche das Event einereits um dem Benutzer mehr Zeilen anzufügen für die nächste Eingabe, andererseits um Fehleingaben zu vermeiden. Wenn z.B. in der Tabelle Käse steht will ich den OK-Button so deaktivieren.
 

dzim

Top Contributor
Nun ja, i.d.R. passt du damit ja dein darunterliegendes Modell an - also müsstest du dort auf Änderungen hören (du musst dazu natürlich JavaFX-Properties (StringProperty, etc.) verwenden). Grundsätzlich ist das einfach, aber du wirst wahrscheinlich eher ein Custom-Event in deinem Cell-Editor (irgendsoetwas wird es auch im ControlsFX-SpreadsheetView geben, denke ich) auslösen müssen.
IMHO Einfachste Variante: Im Cell-Editor den Wert einer ObjectPropert<DeinModellTyp> anpassen und einen Listener darauf registrieren, der den Ok-Button enabled/disabled.
 

White_Fox

Top Contributor
Irgendwie kapiere ich das Konzept hinter der TableView einfach nicht...aber ich hatte in den letzten Tagen auch keine Zeit um mich damit zu befassen.

Erstmal zusehen daß ich die TableView mit Werten gefüllt kriege. Noch nicht mal das läuft gerade...
 

White_Fox

Top Contributor
Hast du vielleicht ein Beispiel dazu?

Wenn es mit SpreadsheetView auch geht würde ich auch dabei bleiben. Es geht mir nur darum, den Benutzer beliebig viele Wertepaare erstellen zu lassen die am Ende in einer HashMap landen sollen.
 

White_Fox

Top Contributor
So...jetzt gehts bei meinem Projekt wieder weiter, ich war etwas arg beschäftigt in den letzten Wochen.

Vielen Dank für deine Beispiele und daß du die so großzügig online gestellt hast. Ich find das gut. :)
Ich hab mein Programm wieder auf SpreadsheetView umgestrickt. Einerseits weil ich damit besser klarkomme, und es mir die TableView keinen Vorteil bringt weil ich Daten modellieren muß, die es noch gar nicht gibt.
Und so wie ich das sehe brauche ich ein Custom-Event, egal welche Variante ich nehme.

Und da wäre ich schon bei meiner Bitte: Hättest du vielleicht auch ein Beispiel, wie man mit Custom-Events arbeitet? Die Beispiele, die ich dazu finde, greifen leider etwas zu kurz bzw. sehe ich nicht, wie ich das auf Änderungen in Zellen anwenden kann.
 

White_Fox

Top Contributor
Hat irgendjemand eine Idee, warum das hier nicht kompilieren will?
Code:
Grid pairTableGrid = new GridBase(0, 0);

pairTableGrid.addEventHandler(GridChange.ANY, new EventHandler<GridChange>(){
  @Override
  public void handle(GridChange event) {
    System.out.println("Eventtype: " + event.getEventType().getName());
  }
});

Netbeans meckert: "method addEventHandler in Interface Grid cannot be applied to given Types..."


Nachtrag:
Ich habs hingekriegt:
Anstatt GridChange.ANY muß der Handler für GridChange.GRID_CHANGE_EVENT angemeldet werden. Dann kommt ein Event sobald eine Zelle geändert wird.
 
Zuletzt bearbeitet:

White_Fox

Top Contributor
...und schon folgt das nächste Problem. Folgendes:
Code:
pairTable = new SpreadsheetView();
rows = FXCollections.observableArrayList();
row = FXCollections.observableArrayList();
row.add(SpreadsheetCellType.STRING.createCell(0, 0, 1, 1, ""));
row.add(SpreadsheetCellType.STRING.createCell(0, 1, 1, 1, ""));
rows.add(row);
pairTableGrid = new GridBase(0, 0);

pairTableGrid.addEventHandler(GridChange.GRID_CHANGE_EVENT, new EventHandler<GridChange>() {
   @Override
   public void handle(GridChange event) {
       int i;
       ObservableList<SpreadsheetCell> row;
       ObservableList<ObservableList<SpreadsheetCell>> rows;

       event.consume();
       rows = pairTableGrid.getRows();

       //Delete row if it is empty and not last
       i = 0;
       while (i < rows.size() - 1) {
           row = rows.get(i);
           if (row.get(0).getText().equals("") && row.get(1).getText().equals("")) {
               rows.remove(i);
           } else {
               i++;
           }
       }

       //Add new row if neccessary
       row = rows.get(rows.size() - 1);
       if (!row.get(0).getText().equals("")) {
           row = FXCollections.observableArrayList();
           row.add(SpreadsheetCellType.STRING.createCell(0, rows.size(), 1, 1, ""));
           row.add(SpreadsheetCellType.STRING.createCell(1, rows.size(), 1, 1, ""));
           rows.add(row); //### Hier tritt das Problem auf ###
       }
       //Todo: remove duplicates
   }
});

pairTableGrid.setRows(rows);

Ich will die Tabelle als Eingabemöglichkeit benutzen. Wenn der Bentzer etwas eingibt, soll eine zusätzliche Zeile eingefügt werden. Das funktioniert auch soweit.

Allerdings schmeißt der Code eine Exception, wenn ich dem ganzen Gebilde eine zusätzliche Zeile einfüge (siehe Codekommentar). Hat jemand eine Idee, wie ich dies vermeiden kann?

Nachtrag: Ich hab schon überlegt ob ich einen EventHandler auf die SpreadsheetCell-Objekte ansetzen kann, aber SpreadsheetCell unterstützt kein passendes Event.

Exception hat gesagt.:
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 impl.org.controlsfx.spreadsheet.GridViewBehavior.selectCell(GridViewBehavior.java:325)
at impl.org.controlsfx.spreadsheet.GridCellEditor.endEdit(GridCellEditor.java:138)
at impl.org.controlsfx.spreadsheet.GridCellEditor$2.changed(GridCellEditor.java:259)
at impl.org.controlsfx.spreadsheet.GridCellEditor$2.changed(GridCellEditor.java:255)
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:361)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:72)
at javafx.scene.Node$FocusedProperty.notifyListeners(Node.java:7718)
at javafx.scene.Scene$13.invalidated(Scene.java:2077)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:111)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.Scene$KeyHandler.setFocusOwner(Scene.java:3924)
at javafx.scene.Scene$KeyHandler.requestFocus(Scene.java:3971)
at javafx.scene.Scene$KeyHandler.access$1900(Scene.java:3910)
at javafx.scene.Scene.requestFocus(Scene.java:2044)
at javafx.scene.Node.requestFocus(Node.java:7879)
at javafx.scene.control.ControlUtils.requestFocusOnControlOnlyIfCurrentFocusOwnerIsChild(ControlUtils.java:65)
at javafx.scene.control.TableCell.cancelEdit(TableCell.java:391)
at impl.org.controlsfx.spreadsheet.CellView.cancelEdit(CellView.java:234)
at javafx.scene.control.TableCell.updateEditing(TableCell.java:565)
at javafx.scene.control.TableCell.lambda$new$26(TableCell.java:142)
at javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:83)
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:349)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyObjectPropertyBase.fireValueChangedEvent(ReadOnlyObjectPropertyBase.java:74)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:102)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.control.TableView.setEditingCell(TableView.java:1145)
at javafx.scene.control.TableView.edit(TableView.java:1457)
at impl.org.controlsfx.spreadsheet.GridViewSkin.edit(GridViewSkin.java:1177)
at impl.org.controlsfx.spreadsheet.GridViewSkin.edit(GridViewSkin.java:91)
at com.sun.javafx.scene.control.skin.TableViewSkinBase.lambda$new$70(TableViewSkinBase.java:293)
at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.transformation.SortedList.sourceChanged(SortedList.java:114)
at javafx.collections.transformation.TransformationList.lambda$getListener$23(TransformationList.java:106)
at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.transformation.FilteredList.sourceChanged(FilteredList.java:147)
at javafx.collections.transformation.TransformationList.lambda$getListener$23(TransformationList.java:106)
at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at main.view.stampeditor.IfThenStampeditor$1.handle(IfThenStampeditor.java:102)
at main.view.stampeditor.IfThenStampeditor$1.handle(IfThenStampeditor.java:75)
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.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
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:49)
at javafx.event.Event.fireEvent(Event.java:198)
at org.controlsfx.control.spreadsheet.GridBase.setCellValue(GridBase.java:240)
at impl.org.controlsfx.spreadsheet.GridCellEditor.endEdit(GridCellEditor.java:130)
at org.controlsfx.control.spreadsheet.SpreadsheetCellEditor.endEdit(SpreadsheetCellEditor.java:181)
at org.controlsfx.control.spreadsheet.SpreadsheetCellEditor$StringEditor$1.handle(SpreadsheetCellEditor.java:380)
at org.controlsfx.control.spreadsheet.SpreadsheetCellEditor$StringEditor$1.handle(SpreadsheetCellEditor.java:376)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3964)
at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$352(GlassViewEventHandler.java:248)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:966)
at com.sun.glass.ui.win.WinApplication._enterNestedEventLoopImpl(Native Method)
at com.sun.glass.ui.win.WinApplication._enterNestedEventLoop(WinApplication.java:204)
at com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:511)
at com.sun.glass.ui.EventLoop.enter(EventLoop.java:107)
at com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:590)
at javafx.stage.Stage.showAndWait(Stage.java:474)
at main.view.View.addNewStampToStampset(View.java:555)
at main.view.View.access$200(View.java:66)
at main.view.View$StamptableContextmenu$4.handle(View.java:120)
at main.view.View$StamptableContextmenu$4.handle(View.java:117)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
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:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
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.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)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at impl.org.controlsfx.spreadsheet.GridCellEditor.endEdit(GridCellEditor.java:132)
at org.controlsfx.control.spreadsheet.SpreadsheetCellEditor.endEdit(SpreadsheetCellEditor.java:181)
at org.controlsfx.control.spreadsheet.SpreadsheetCellEditor$StringEditor$1.handle(SpreadsheetCellEditor.java:380)
at org.controlsfx.control.spreadsheet.SpreadsheetCellEditor$StringEditor$1.handle(SpreadsheetCellEditor.java:376)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3964)
at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$352(GlassViewEventHandler.java:248)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:966)
at com.sun.glass.ui.win.WinApplication._enterNestedEventLoopImpl(Native Method)
at com.sun.glass.ui.win.WinApplication._enterNestedEventLoop(WinApplication.java:204)
at com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:511)
at com.sun.glass.ui.EventLoop.enter(EventLoop.java:107)
at com.sun.javafx.tk.quantum.QuantumToolkit.enterNestedEventLoop(QuantumToolkit.java:590)
at javafx.stage.Stage.showAndWait(Stage.java:474)
at main.view.View.addNewStampToStampset(View.java:555)
at main.view.View.access$200(View.java:66)
at main.view.View$StamptableContextmenu$4.handle(View.java:120)
at main.view.View$StamptableContextmenu$4.handle(View.java:117)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
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.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
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:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
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.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)
 

mihe7

Top Contributor
Achtung: ich nix JavaFX :) Vielleicht mag das Teil es nicht, wenn während eines Change-Events das Grid nochmal geändert wird. Pack die Zeile rows.add(row) mal versuchsweise in ein Platform.invokeLater.
 

White_Fox

Top Contributor
Hallo mihe7 :)

Ein Platform.invokeLater scheint es nicht zu geben, dafür aber ein Platform.runLater().

Diese Methode nimmt nun ein Runnable (neuer Thread) entgegen.
Also:
Code:
private class RowAdder implements Runnable{
       private ObservableList<ObservableList<SpreadsheetCell>> rows;
       private ObservableList<SpreadsheetCell> row;
       
       public RowAdder(ObservableList<ObservableList<SpreadsheetCell>> rows,
               ObservableList<SpreadsheetCell> row){
           this.rows = rows;
           this.row = row;
       }
       @Override
       public void run() {
           rows.add(row);
       }
}

...
//rows.add(row);
Platform.runLater(new RowAdder(rows, row));
...

Das funktioniert auch ganz fabelhaft...aber leider nur einmal. Danach steckt die Methode wieder im gleichen Dilemma fest. Und ich verstehe absolut nicht warum.
 

mihe7

Top Contributor
Platform.invokeLater
Oh, wie gesagt: ich nix JavaFX - invokeLater ist Swing :)

Nein, nicht neuer Thread. Du befindest Dich im UI-Thread. Das Runnable wird einfach in die Queue eingereiht, die vom UI-Thread abgearbeitet wird.

Statt dem RowAdder kannst Du kurz auch schreiben:
Java:
//rows.add(row);
Platform.runLater(() -> rows.add(row));

Danach steckt die Methode wieder im gleichen Dilemma fest. Und ich verstehe absolut nicht warum.
Das verstehe ich allerdings auch nicht, warum es einmal funktioniert und beim zweiten Mal nicht mehr.

Vielleicht schaue ich mir das nachher mal Live an.
 

White_Fox

Top Contributor
Nein, nicht neuer Thread. Du befindest Dich im UI-Thread. Das Runnable wird einfach in die Queue eingereiht, die vom UI-Thread abgearbeitet wird
Hö...? Ich hab Runnable heute zwar zum ersten Mal benutzt, bin da aber oft drüber gestolpert als ich mich mit Multithreading beschäftigt habe. Da hab ich im Wesentlichen zwei Methoden gefunden um Threads zu starten: Runnable implementieren oder von Thread ableiten (ich hab bisher immer letzteres gemacht).
Oder ist das ein anderes Runnable?

Ansonsten hab ich den RowAdder-Aufruf mal so gestartet wie du es vorgeschlagen hast...immer noch mit demselben Ergebnis. :(

Vielleicht schaue ich mir das nachher mal Live an.
Das wäre große Klasse. :)
 

mihe7

Top Contributor
Zum Runnable: Wenn Du einen neuen Thread erzeugst, erwarten einige der Konstruktoren von java.lang.Thread ein Objekt, das das Runnable-Interface implementiert. Runnable selbst ist ein stinknormales Interface mit einer Methode: void run().

Der UI-Thread macht - vereinfacht ausgedrückt - nichts anderes, als aus einer Warteschlange Objekte zu entnehmen. Handelt es sich um ein Runnable wird einfach die run()-Methode aufgerufen, die somit im UI-Thread ausgeführt wird.

Zum Problem: bin noch nicht zum Implementieren gekommen, dauert also noch :)
 

mihe7

Top Contributor
So, jetzt habe ich mal was zusammengeschustert:
Java:
import javafx.application.*;
import javafx.collections.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.stage.*;
import org.controlsfx.control.spreadsheet.*;

public class Test extends Application {
    private void handle(GridChange event) {
        event.consume();
        GridBase grid = (GridBase) event.getTarget();
        ObservableList<ObservableList<SpreadsheetCell>> rows = grid.getRows();
        int lastRow = rows.size() - 1;
        if (event.getRow() == lastRow) {
            if (event.getNewValue() != null) {        
                Platform.runLater(() -> addEmptyRow(rows));
            }
        }
    }

    private void addEmptyRow(ObservableList<ObservableList<SpreadsheetCell>> rows) {
        ObservableList<SpreadsheetCell> row;
        row = FXCollections.observableArrayList();
        int ix = rows.size();
        row.add(SpreadsheetCellType.STRING.createCell(ix, 0, 1, 1, ""));
        row.add(SpreadsheetCellType.STRING.createCell(ix, 1, 1, 1, ""));
        rows.add(row);
    }

    public void start(Stage stage) {
        ObservableList<SpreadsheetCell> row;
        ObservableList<ObservableList<SpreadsheetCell>> rows;

        rows = FXCollections.observableArrayList();
        addEmptyRow(rows);
        GridBase grid = new GridBase(0, 0);
        grid.addEventHandler(GridChange.GRID_CHANGE_EVENT, this::handle);
        grid.setRows(rows);
        SpreadsheetView root = new SpreadsheetView(grid);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
}
 

mihe7

Top Contributor
Da werden du und JavaFX ja vielleicht doch noch Freunde
LOL - wer weiß? Ich glaube aber eher nicht. Das ist mir zu restriktiv und irgendwo auch zu intrusiv.

Man kann schnell was zusammenklicken, sobald man aber nur ein wenig von dem abweicht, was die Komponenten bieten, wird der Aufwand unverhältnismäßig hoch. Wenn Du Dich erinnerst: wir hatten hier z. B. das Problem mit einem Label, das anhand der Länge etwas anderes darstellen sollte. Die einzig einfache Lösung war ein Würg-around, die andere war, eine eigene Komponente zu erstellen, wobei dann Code von Label kopiert hätte werden müssen, weil dort alles private und somit in abgeleiteten Komponenten nicht verfügbar ist. Das erinnert mich sehr an 4GL-Sprachen.

Und wer kommt bitte auf die Idee, das halbe java.lang.* nachzuprogrammieren, angereichert um gefühlte 3 Mio. zusätzliche Methoden, um so sinnvolle Dinge wie NumberBinding result = Bindings.add (a.multiply(b), c.multiply(d)); schreiben zu können?

Weil ich Dich gerade da habe ;): wie bindet man eigentlich ein TextField an ein BigDecimal inkl. Formatierung?
 

Robat

Top Contributor
Weil ich Dich gerade da habe ;): wie bindet man eigentlich ein TextField an ein BigDecimal inkl. Formatierung
Meinst du sowas in der Art?
Java:
public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Foo foo = new Foo(BigDezimal.ZERO);
        foo.fooProperty().addListener((obs, oldVal, newVal) -> System.out.printf("changed from %s to %s%n", oldVal, newVal));
       
        TextField textField = new TextField();
        textField.textProperty().bind(
                Bindings.createStringBinding(
                        () -> new DecimalFormat("#0.##").format(foo.getFoo()), foo.fooProperty()));

        Button btn = new Button("Foo");
        btn.setOnAction(e -> foo.setFoo(new BigDecimal(Math.random())));

        HBox root = new HBox();
        root.getChildren().addAll(textField, btn);

        primaryStage.setScene(new Scene(root));
        primaryStage.show();

    }
    class Foo {
        private ObjectProperty<BigDecimal> foo;

        public Foo(BigDecimal foo) {
            this.foo = new SimpleObjectProperty<>(foo);
        }

        public void setFoo(BigDecimal foo) {
            this.foo.set(foo);
        }

        public BigDecimal getFoo() {
            return foo.get();
        }

        public ObjectProperty<BigDecimal> fooProperty() {
            return foo;
        }
    }
}
 

Robat

Top Contributor
Ja an die Sache mit dem Label erinnere ich mich und auch die "Würg-arounds" (schönes Wort btw ;) ). Du hast schon Recht .. in vielen Aspekten scheint der Aufwand sehr groß zu sein aber ich muss sagen, dass man auch vieles verallgemeinern kann und sich den Aufwand nur einmal antun muss. Das ganze ist natürlich nur sinnvoll, wenn man öfter mit JavaFX zu tun hat. Für ein kleines Projekt ist es ggf. zu viel.

Und wer kommt bitte auf die Idee, das halbe java.lang.* nachzuprogrammieren, angereichert um gefühlte 3 Mio. zusätzliche Methoden, um so sinnvolle Dinge wie NumberBinding result = Bindings.add (a.multiply(b), c.multiply(d)); schreiben zu können?
Zu viel Zeit würde ich mal sagen :D
 

mihe7

Top Contributor
Gibt es ein GUI-Framework, wo das anders ist?
Ja. Swing ist das genaue Gegenteil davon. Da hast Du von Haus aus etwas mehr Arbeit, weil alles darauf ausgelegt ist, erweitert/angepasst zu werden. Dafür kannst Du aber auch alles erweitern/anpassen und - was die Funktionalität betrifft - meist mit relativ wenig Aufwand.

Swing hat viele Mankos, das ist gar keine Frage. Das Framework ist uralt. Eine Swing-Anwendung optisch ansprechend zu gestalten, ist sehr viel aufwändiger als eine JavaFX-Anwendung, auch weil man nicht einfach per CSS ein paar Styles setzen kann. Die grafischen Möglichkeiten bzgl. Animationen/Multimedia sind sehr beschränkt und die Web-Unterstützung ist nur sehr rudimentär vorhanden. Kurz: es ist halt einfach alt.

In JavaFX sind die Komponenten dagegen so stark gekapselt, dass dieser Teil für mich nichts mehr mit einem Framework zu tun hat. Das ist eher eine Komponentenbibliothek, die nach dem Motto "friss oder stirb" zu verwenden ist.

Bestes Beispiel: https://www.java-forum.org/thema/alternativtext.182407/ Das ist doch ein Witz.
 

Robat

Top Contributor
Ah also bidirektional? Dann das Binding ggf so anpassen (oder nach deinen Wünschen :p ):
Java:
textField.textProperty().bindBidirectional(foo.fooProperty(), new StringConverter<>() {
    @Override
    public String toString(BigDecimal object) {
        return new DecimalFormat("#0.##").format(object);
    }

    @Override
    public BigDecimal fromString(String string) {
        return new BigDecimal(string.replaceAll(",", "."));
    }
});
 

White_Fox

Top Contributor
Dafür kannst Du aber auch alles erweitern/anpassen und - was die Funktionalität betrifft - meist mit relativ wenig Aufwand.
Ich hab die GUI von meinem Programm ja mit Swing angefangen. Ja, ist alt, aber die GUI von Netbeans z.B. ist meines Wissens nach auch in Swing gemacht, und ich finde das durchaus noch brauchbar.

Auf JavaFX bin ich umgestiegen, weil Tabellen so umständlich anzupassen (konkret: Zellverbünde) sind. Jedenfalls scheine ich nicht der Erste zu sein der sowas haben wollte und dann mit JavaFX anstatt Swing weitergemacht hat.
 

Robat

Top Contributor
Zuletzt bearbeitet:

mihe7

Top Contributor
Ähnliche Java Themen
  Titel Forum Antworten Datum
berserkerdq2 Mein Rechteck hat 4 Seiten, ich soll je nach dem, welche Seite berührt wurde, etwas ausführen, wie prüfe ich das? AWT, Swing, JavaFX & SWT 12
W JavaFX CSS und Vererbung - ich brauche nochmal etwas Nachhilfe AWT, Swing, JavaFX & SWT 28
F Popup Menu etwas verschieben AWT, Swing, JavaFX & SWT 2
steven789hjk543 Swing Verstehe etwas beim GUI nicht AWT, Swing, JavaFX & SWT 3
D JavaFX Erkennen wenn eine Anwendung geschlossen wird und etwas tun? AWT, Swing, JavaFX & SWT 4
B Graphics -> Graphics2D etwas zu beachten? AWT, Swing, JavaFX & SWT 8
A Swing " comboboxes vergl. wenn aus der 1. etwas gewählt wurde ist, es in der 2. nicht mehr sichtbar AWT, Swing, JavaFX & SWT 9
B Etwas was nach jedem GUI 'click' ausgeführt wird AWT, Swing, JavaFX & SWT 6
J Zählen, wie oft etwas gezeichnet wird AWT, Swing, JavaFX & SWT 2
V Nullpointerexception (etwas mit thread und jframe) AWT, Swing, JavaFX & SWT 3
C Etwas durchsichtig machen über einem Panel AWT, Swing, JavaFX & SWT 7
M Dialog soll etwas an "Oberklasse" übergeben AWT, Swing, JavaFX & SWT 3
P Action Event abfangen etwas anders? AWT, Swing, JavaFX & SWT 2
E etwas anderer rahmen. AWT, Swing, JavaFX & SWT 2
F gibt etwas wie frames in html auch in java? AWT, Swing, JavaFX & SWT 19
T JLayerdPane: wie etwas über eine AWT Komponente zeichen? AWT, Swing, JavaFX & SWT 2
J Gui soll sich ändern wenn etwas passiert AWT, Swing, JavaFX & SWT 11
W aus JList etwas löschen AWT, Swing, JavaFX & SWT 9
M Swing Cell Renderer für Zeilenumbruch in JTable AWT, Swing, JavaFX & SWT 0
J CheckTreeView mit eigenem Cell Value AWT, Swing, JavaFX & SWT 3
E JavaFX Von der Table-Cell zur Row AWT, Swing, JavaFX & SWT 0
K JavaFX Mehrere Cell Editors in einem TreeView Item AWT, Swing, JavaFX & SWT 2
X JavaFX TableView selektierung der cell wie begrenzen? AWT, Swing, JavaFX & SWT 0
S SWT TableCell mit Composite als Inhalt / Höhe der Cell/Row AWT, Swing, JavaFX & SWT 5
M JTable Cell Renderer- Terminplaner AWT, Swing, JavaFX & SWT 2
A JTable Cell Eingabe AWT, Swing, JavaFX & SWT 6
T JTable Cell Refresh AWT, Swing, JavaFX & SWT 5
B Row und Cell Änderungen feststellen AWT, Swing, JavaFX & SWT 3
H default cell renderer AWT, Swing, JavaFX & SWT 3
J Swing JTable cell-ausrichtung für zahlen mit alternierenden zeilenfarben AWT, Swing, JavaFX & SWT 2
A Swing JButton in einer Table Cell AWT, Swing, JavaFX & SWT 9
B LookAndFeel Cell Renderer für JTable bei Nimbus Look and Feel AWT, Swing, JavaFX & SWT 2
M Swing JTable cell leeren bei Eingabe AWT, Swing, JavaFX & SWT 6
C Swing JTable: edit Cell -> versteckten Wert ändern AWT, Swing, JavaFX & SWT 12
A Focus in JTable Cell AWT, Swing, JavaFX & SWT 3
S Color in Cell AWT, Swing, JavaFX & SWT 2
O JTable Edit cell edit end erzwingen... AWT, Swing, JavaFX & SWT 7
G Cell Renderer AWT, Swing, JavaFX & SWT 5
Tom299 Cell Renderer mit Link AWT, Swing, JavaFX & SWT 2
O JCombobox in EINER JTable Cell AWT, Swing, JavaFX & SWT 5
D Problem bei meinem Cell Renderer AWT, Swing, JavaFX & SWT 2
J Cell Farbe in JTable AWT, Swing, JavaFX & SWT 31
C Proleme mit eigenem Cell Renderer AWT, Swing, JavaFX & SWT 3
H mehrere cell renderers AWT, Swing, JavaFX & SWT 5
M Select cell AWT, Swing, JavaFX & SWT 3
S JTable - farbe einer cell/row ändern, Hilfe please AWT, Swing, JavaFX & SWT 2
clemson Cursor in JTable-Cell setzen AWT, Swing, JavaFX & SWT 6
D JTable - Hintergrundbild in Cell AWT, Swing, JavaFX & SWT 6

Ähnliche Java Themen

Neue Themen


Oben