2017-01-02 16 views
0

мне нужна помощь по следующим основным вопросам:Tornadofx TableView с использованием COMBOBOX & добавление FXEvent на кнопках

Требование:
У меня есть TableView, который может быть отредактирован (рядный) и строки могут быть удалены слишком, а также в случае необходимости некоторые сложные операции при нажатии кнопки.

Мой Take, ниже находятся 3 небольшие проблемы:

  1. Я создал TableView с IsEditable = истинным и сделал имя столбца в редактируемые. Но когда я редактирую, он не привязывается к модели. (Должно отсутствовать очень простая вещь)
  2. При редактировании comboBox показывает параметры, но при выборе значения генерирует исключение.

java.lang.ClassCastException: javafx.beans.property.SimpleStringProperty не может быть приведен к javafx.beans.property.ObjectProperty

Затем я добавил кнопку удаления, которая работает отлично, когда я раскомментировал tableView.items.removeAt (index)
Но, поскольку я хочу некоторые дополнительные функции, я решил пойти с огнем FXEvent. Но как я должен использовать это здесь.

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 - что заставляет думать, что он не привязан к модели - он работает для меня? Вы попадаете на вход в ячейку таблицы (просто потеря фокуса не приводит к фиксации)? – stacktrace

+0

О, мой плохой ... Я не нажимал кнопку ввода, я щелкал снаружи, думая, что он будет автоматически связываться (исходя из углового мира). Но да, функциональность имеет смысл. – mercy123

ответ

2

Чтобы получить доступ к EventBus с внешней стороной Component, используйте переменную FX.eventbus, и огнь события на что:

FX.eventbus.fire(DeleteEvent(index)) 

Причину вы получите сообщение об ошибке, когда вы измените значение в поле со списком является ошибкой в ​​рамках. Я только что совершил исправление для него, но вы можете обойти это путем добавления этой функции расширения для вашего приложения до 1.5.10 релиза:

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 
} 

Просто позвоните .useComboBoxWorking() вместо сейчас, и вы должны быть золотыми:)

Если вы не хотите использовать обходной путь, вы можете временно изменить genderProperty вашего Warrior быть типа SimpleObjectProperty<String> вместо SimpleStringProperty в качестве альтернативы.

+0

Спасибо :) ... теперь все работает так, как ожидалось. – mercy123