Asyn c Загрузка TreeView - PullRequest
       21

Asyn c Загрузка TreeView

0 голосов
/ 17 февраля 2020

Эй, я новичок в tornadofx, борясь с асин c загрузка данных для дерева. Я загружаю категории из конечной точки отдыха, которую я хочу показать там.

Кажется, что нет прямой привязки данных к дочерним элементам.

при использовании 'bindChildren' я могу предоставить Наблюдаемый список, но я должен преобразовать их в Node's. что тогда сделало бы блок заселения своего рода устаревшим.

Какой рекомендуемый способ сделать это? Я ничего не могу найти по этому поводу.

// Category
interface Category<T : Category<T>> {
  val id: String
  val name: String
  val subcategories: List<T>?
}


//default category:
class DefaultCategory(override val name: String) : Category<DefaultCategory> {
  override val id: String = "default"
  override val subcategories: List<DefaultCategory>? = null
}
//ViewModel
class CategoryViewModel : ViewModel() {
  val sourceProperty = SimpleListProperty<Category<*>>()
  fun loadData() {
    // load items for treeview into 'newItems'
    sourceProperty.value = newItems
  }
}

// TreeViewFactoryMethod
private fun createTreeView(
  listProperty: SimpleListProperty<Category<*>>
): TreeView<Category<*>> {
  return treeview {
    root = TreeItem(DefaultCategory("Categories"))
    isShowRoot = false
    root.isExpanded = true
    root.children.forEach { it.isExpanded = true }
    cellFormat { text = it.name }
    populate { parent ->
      when (parent) {
        root -> listProperty.value
        else -> parent.value.subcategories
      }
    }
  }
}

Предполагая, что при нажатии кнопки я вызываю viewmodel.loadData(), я ожидаю, что TreeView обновится, как только появятся новые данные. (Если бы я нашел способ связать)

1 Ответ

0 голосов
/ 17 февраля 2020

Раньше мне никогда не приходилось использовать bindChildren для TornadoFX, а использование asyn c не очень важно для того, что я считаю вашей основной проблемой. Итак, по общему признанию, этот вопрос сначала смутил меня, но я предполагаю, что вам просто интересно, почему список не появляется в вашем TreeView? Я сделал тестовый пример с изменениями, чтобы он работал.

// Category
interface Category<T : Category<T>> {
    val id: String
    val name: String
    val subcategories: List<T>?
}

//default category:
class DefaultCategory(override val name: String) : Category<DefaultCategory> {
    override val id: String = "default"
    override val subcategories: List<DefaultCategory>? = null
}
//Just a dummy category
class ChildCategory(override val name: String) : Category<ChildCategory> {
    override val id = name
    override val subcategories: List<ChildCategory>? = null
}

//ViewModel
class CategoryViewModel : ViewModel() {
    //filled with dummy data
    val sourceProperty = SimpleListProperty<Category<*>>(listOf(
            ChildCategory("Categorya"),
            ChildCategory("Categoryb"),
            ChildCategory("Categoryc"),
            ChildCategory("Categoryd")
    ).asObservable())

    fun loadData() {
        sourceProperty.asyncItems {
            //items grabbed somehow
            listOf(
                    ChildCategory("Category1"),
                    ChildCategory("Category2"),
                    ChildCategory("Category3"),
                    ChildCategory("Category4")
            ).asObservable()
        }
    }
}


class TestView : View() {
    val model: CategoryViewModel by inject()

    override val root = vbox(10) {
        button("Refresh Items").action {
            model.loadData()
        }
        add(createTreeView(model.sourceProperty))
    }

    // TreeViewFactoryMethod
    private fun createTreeView(
            listProperty: SimpleListProperty<Category<*>>
    ): TreeView<Category<*>> {
        return treeview {
            root = TreeItem(DefaultCategory("Categories"))
            isShowRoot = false
            root.isExpanded = true
            root.children.forEach { it.isExpanded = true }
            cellFormat { text = it.name }
            populate { parent ->
                when (parent) {
                    root -> listProperty
                    else -> parent.value.subcategories
                }
            }
        }
    }
}

Есть 2 важных отличия, которые важны.

1. Более важное различие заключается в том, что внутри блока заполнения вместо root.listProperty.value используется root -> listProperty. Это сделает ваш список появиться. Причина в том, что SimpleListProperty не является списком, он содержит список. Так что да, передача в простой список вполне допустима (например, как вы передали значение свойства списка). Но теперь это означает, что древовидное представление не слушает вашу собственность, а только список, который вы передали. Имея это в виду, я бы подумал над реализацией списков подкатегорий категорий.

2. Во-вторых, обратите внимание на использование asyncItems в ViewModel. Это будет выполнять любую задачу асинхронно, а затем установить список элементов в случае успеха. Вы можете даже добавить fail или cancel блоки к нему. Я бы рекомендовал использовать это, поскольку длинные / интенсивные операции не должны выполняться в потоке пользовательского интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...