2017-01-02 5 views
0

ich Hilfe auf den folgenden grundlegenden Fragen müssen:Tornadofx Tableview mit comboBox & Hinzufügen FXEvent auf Tasten

Voraussetzung:
Ich habe eine Tableview, die (Inline) bearbeitet werden können und Zeilen zu gelöscht werden können und bei Bedarf auch einige komplexe Vorgänge auf Knopfdruck.

Mein nehmen, unten sind die drei kleine Probleme:

  1. Ich habe eine Tableview mit isEditable = true und machte Spaltennamen als editierbar. Aber wenn ich es bearbeite, bindet es nicht an das Modell. (Muss eine sehr einfache Sache fehlen)
  2. Bei der Bearbeitung zeigt das Kombinationsfeld die Optionen an, aber beim Auswählen eines Wertes wird eine Ausnahme ausgelöst.

java.lang.ClassCastException: javafx.beans.property.SimpleStringProperty kann nicht auf javafx.beans.property.ObjectProperty

Dann gegossen werden, habe ich eine Löschtaste hinzugefügt, die funktioniert gut, wenn ich Kommentar tableView.items.removeAt (Index)
Aber da ich einige zusätzliche Funktionen möchte, entschied ich mich, mit dem FXEvent Feuer gehen. Aber wie soll ich das hier benutzen?

class MyView : View() { 
    val warriorModel : WarriorModel by inject() 
    val persons = FXCollections.observableArrayList<Warrior>(
      Warrior(1,"Tyrion Lannister", "M"), 
      Warrior(2,"Ned Stark", "M"), 
      Warrior(3,"Daenerys Targaryen", "F"), 
      Warrior(4,"Arya Stark", "F") 
    ) 
    override val root = vbox { 
     tableview(persons) { 
      isEditable = true 
      column("ID", Warrior::idProperty) 
      column("Name", Warrior::nameProperty).makeEditable() 
      column("Gender", Warrior::genderProperty).useComboBox(FXCollections.observableArrayList("M", "F")) 
      column("Action", Warrior::dummyProperty).setCellFactory { DeleteButton<Warrior>() } 
      bindSelected(warriorModel) 
      subscribe<DeleteEvent> { event -> 
       items.removeAt(event.index) 
      } 
     } 
    } 
} 
class DeleteButton<Warrior>() : TableCell<Warrior, String?>() { 
    internal val btn = Button("Delete") 
    override fun updateItem(item: String?, empty: Boolean) { 
     super.updateItem(item, empty) 
     if (empty) { 
      graphic = null 
      text = null 
     } else { 
      btn.setOnAction { event: ActionEvent -> 
       //tableView.items.removeAt(index) 
       fire(DeleteEvent(index)) 
      } 
      graphic = btn 
      text = null 
     } 
    } 
} 
class Warrior(id: Int, name: String, gender: String) { 

    val idProperty = SimpleIntegerProperty(id) 
    var id by idProperty 

    val nameProperty = SimpleStringProperty(name) 
    var name by nameProperty 

    val genderProperty = SimpleStringProperty(gender) 
    var gender by genderProperty 

    val dummyProperty = SimpleStringProperty("") 
} 
class WarriorModel : ItemViewModel<Warrior>() { 
    val id = bind { item?.idProperty } 
    val name = bind { item?.nameProperty } 
    val gender = bind { item?.genderProperty } 
} 
class DeleteEvent(val index: Int) : FXEvent() 
+0

re: # 1 - was macht denken, dass es nicht an das Modell bindet - funktioniert es für mich? Triffst du die Eingabe in die Tabellenzelle (nur das Verlieren des Fokus erzwingt kein Commit)? – stacktrace

+0

Oh ... mein Schlechter ... Ich drückte nicht Enter, ich klickte draußen und dachte, es würde sich automatisch verbinden (aus einer eckigen Welt kommend) .. Aber ja, die Funktionalität macht Sinn. – mercy123

Antwort

2

Um die EventBus von außerhalb eines Component zuzugreifen, verwenden Sie die FX.eventbus Variable und feuern das Ereignis auf, dass:

FX.eventbus.fire(DeleteEvent(index)) 

Der Grund, warum Sie den Fehler erhalten, wenn Sie den Wert in der Combobox ändern ist ein Fehler im Framework. Ich habe verpflichtet nur eine Lösung für sie, aber man kann durch das Hinzufügen dieser Erweiterungsfunktion, um Ihre Anwendung bis zum 1.5.10 Release um es:

fun <S, T> TableColumn<S, T?>.useComboBoxWorking(items: ObservableList<T>, afterCommit: ((TableColumn.CellEditEvent<S, T?>) -> Unit)? = null): TableColumn<S, T?> { 
    cellFactory = ComboBoxTableCell.forTableColumn(items) 
    setOnEditCommit { 
     val property = it.tableColumn.getCellObservableValue(it.rowValue) as Property<T?> 
     property.value = it.newValue 
     afterCommit?.invoke(it) 
    } 
    return this 
} 

Rufen .useComboBoxWorking() stattdessen für jetzt, und Sie sollten golden sein:)

Wenn Sie die Abhilfe nicht verwenden möchten, können Sie vorübergehend die genderProperty Ihrer Warrior ändern Typ SimpleObjectProperty<String> statt SimpleStringProperty als Alternative zu sein.

+0

Danke :) ... jetzt funktioniert alles wie erwartet. – mercy123

Verwandte Themen