[출처 - 이 글은 tornadofx-guide르 통해 공부한 내용을 정리한 글입니다. 더 정확한 내용은 https://edvin.gitbooks.io/tornadofx-guide/part1/5.%20Data%20Controls.html 에서 확인 하실 수 있습니다.]
TreeView
Tree 형태의 View도 생성할 수 있습니다.
data class Person_T(val name: String, val department: String)
val persons_t = listOf(
Person_T("Mary Hanes","Marketing"),
Person_T("Steve Folley","Customer Service"),
Person_T("John Ramsy","IT Help Desk"),
Person_T("Erlick Foyes","Customer Service"),
Person_T("Erin James","Marketing"),
Person_T("Jacob Mays","IT Help Desk"),
Person_T("Larry Cable","Customer Service")
)
class Tree_View : View(){
val departments = persons_t
.map { it.department }
.distinct().map { Person_T(it, "") }
override val root = treeview<Person_T>(){
// Create root item
root = TreeItem(Person_T("Departments", ""))
// Make sure the text in each TreeItem is the name of the Person
cellFormat { text = it.name }
// Generate items. Children of the root item will contain departments
populate { parent ->
if (parent == root) departments else persons_t.filter { it.department == parent.value.name }
}
}
}
class Tree_app:App(Tree_View::class)
fun main() {
launch<Tree_app>()
그 결과는
person_t list에서 department들만 모은 ArrayList를 만든 후
treeView를 구성합니다.
우선 root를 생성 하고, 각 cell의 format을 지정합니다.
그리고 나서 tree를 채워주는데, parent값이 root와 같을 경우 아까 생성한 deparments를 채우고, 그 후
현재 항목의 department와 parent의 name이 값을 경우에 채웁니다.
실행된 항목을 보면
Departments를 생하고, 그 아래 Marketing, Customer Service, IT Help Desk를 채웁니다.
그 후 person_t list의 항목을 하나하나 확인하면서 위의 deparment와 같은 deparment가 있을 경우 하위로 채웁니다.
또한 다른 Type의 item을 사용하여 tree를 만들 수 있습니다.
data class Department(val name: String)
data class Person_T(val name: String, val department: String)
val persons_t = listOf(
Person_T("Mary Hanes","Marketing"),
Person_T("Steve Folley","Customer Service"),
Person_T("John Ramsy","IT Help Desk"),
Person_T("Erlick Foyes","Customer Service"),
Person_T("Erin James","Marketing"),
Person_T("Jacob Mays","IT Help Desk"),
Person_T("Larry Cable","Customer Service")
)
class Differ_type_treeView : View(){
override val root = treeview<Any>{
val departments = persons_t.map { it.department }.distinct().map { Department(it) }
root = TreeItem(Department("Departments"))
cellFormat {
text = when (it) {
is String -> it
is Department -> it.name
is Person_T -> it.name
else -> throw IllegalArgumentException("Invalid value type")
}
}
// Generate items. Children of the root item will contain departments, children of departments are filtered
populate { parent ->
val value = parent.value
if (parent == root) departments
else if (value is Department) persons_t.filter { it.department == value.name }
else null
}
}
}
class Differ_type_app : App(Differ_type_treeView::class)
fun main() {
launch<Differ_type_app>()
}
위의 코드에서 중요한 점은 treeview<Any>로 어떻 타입도 받을 수 있도록 한 부분입니다. 이전 treeView code는 person_t list에서 department를 Person_T 타입으로 Person_T 타입의 List로 departments 만들었다면, 이 code에서는 Department class를 따로 만들어서 department List로 departments를 만들었습니다. 그래서 Person_T와 Department 2개의 타입을 treeview에서 쓸 수 있도록 treeview<Any>로 treeview를 생성합니다.
그리고 그 결과는 다음과 같습니다.
그리고 table 형태의 treeview도 생성할 수 있습니다.
class Person_TT(val name: String,
val department: String,
val email: String,
val employees: List<Person_TT> = emptyList())
val persons_tt = listOf(
Person_TT("Mary Hanes", "IT Administration", "mary.hanes@contoso.com", listOf(
Person_TT("Jacob Mays", "IT Help Desk", "jacob.mays@contoso.com"),
Person_TT("John Ramsy", "IT Help Desk", "john.ramsy@contoso.com"))),
Person_TT("Erin James", "Human Resources", "erin.james@contoso.com", listOf(
Person_TT("Erlick Foyes", "Customer Service", "erlick.foyes@contoso.com"),
Person_TT("Steve Folley", "Customer Service", "steve.folley@contoso.com"),
Person_TT("Larry Cable", "Customer Service", "larry.cable@contoso.com")))
).asObservable()
class Tree_table_view : View(){
override val root = treetableview<Person_TT>().apply {
column("Name", Person_TT::name)
column("Department", Person_TT::department)
column("Email", Person_TT::email)
/// Create the root item that holds all top level employees
root = TreeItem(Person_TT("Employees by leader", "", "", persons_tt))
// Always return employees under the current person
populate { it.value.employees }
// Expand the two first levels
root.isExpanded = true
root.children.forEach { it.isExpanded = true }
// Resize to display all elements on the first two levels
}
}
class Tree_table_app : App(Tree_table_view::class)
fun main() {
launch<Tree_table_app>()
}
위의 방식으로 treetableview를 생성하면 아래와 같은 결과를 얻을 수 있습니다.
(사실 guide에서는 resizeColumnsToFitContent으로 화면 사이즈를 조정하는 method를 사용하고 있는데, 빌드 문제로 NoSuchMethodException이 발생해 제 code에서는 뺐습니다. 그래서 실행을 하면 화면 사이즈가 맞지 않을 것입니다.)
또한 위의 방식 말고도
val tableData = mapOf(
"Fruit" to arrayOf("apple", "pear", "Banana"),
"Veggies" to arrayOf("beans", "cauliflower", "cale"),
"Meat" to arrayOf("poultry", "pork", "beef")
)
class Tree_table_view : View(){
override val root = treetableview<String>(TreeItem("Items")) {
column<String, String>("Type", { it.value.valueProperty() })
populate {
if (it.value == "Items") tableData.keys
else tableData[it.value]?.asList()
}
}
}
class Tree_table_app : App(Tree_table_view::class)
fun main() {
launch<Tree_table_app>()
}
이렇게 작성을 하면
이런 treeview를 생성할 수 있습니다.
DataGrid
DataGrid를 GridPane과 유사합니다. 그럼 code로 확인해 보겠습니다. (dataGird의 경우 Java JDK version 11로 동작 시키면 ClassNotFoundException이 발생하여 동작되지 않습니다. Java JDK version 8로 실행 하시는 것을 추천드립니다. 설정 방법은 제글 TornadoFX - Exception 문제에서 확인 하실 수도 있습니다.)
val images = listOf(
"https://i.imgur.com/DuFZ6PQb.jpg",
"https://i.imgur.com/o2QoeNnb.jpg",
"https://i.imgur.com/C2ZqvPW.jpg",
"https://i.imgur.com/794xc80.jpg",
"https://i.imgur.com/fMZHpun.jpg",
"https://i.imgur.com/VOn4MIx.jpgm",
"https://i.imgur.com/JUJQGs7.jpg",
"https://i.imgur.com/A6oqwNy.jpg"
)
class Grid_view : View(){
override val root = datagrid(images) {
cellCache {
imageview(it)
}
}
}
class Grid_app : App(Grid_view::class)
fun main() {
launch<Grid_app>()
}
이렇게 작성을 한 code를 실행하면 다음과 같은 결과를 받을 수 있습니다.
그런데 위의 결과를 보면 사이즈가 맞지 않아 제대로 나오지 않는 것을 확인할 수 있습니다. 그럴때는 다음과 같이 사이즈를 조절할 수 있습니다.
val images = listOf(
"https://i.imgur.com/DuFZ6PQb.jpg",
"https://i.imgur.com/o2QoeNnb.jpg",
"https://i.imgur.com/C2ZqvPW.jpg",
"https://i.imgur.com/794xc80.jpg",
"https://i.imgur.com/fMZHpun.jpg",
"https://i.imgur.com/VOn4MIx.jpgm",
"https://i.imgur.com/JUJQGs7.jpg",
"https://i.imgur.com/A6oqwNy.jpg"
)
class Grid_view : View() {
override val root = datagrid(images) {
cellCache {
imageview(it) {
this.fitHeight = 100.0
this.fitWidth = 100.0
}
}
}
}
class Grid_app : App(Grid_view::class)
fun main() {
launch<Grid_app>()
}
그리고 클릭도 가능합니다. 또한
val numbers = (1..10).toList()
class Grid_view : View() {
override val root = datagrid(numbers) {
cellHeight = 75.0
cellWidth = 75.0
multiSelect = true
cellCache {
stackpane {
circle(radius = 25.0) {
fill = Color.FORESTGREEN
}
label(it.toString())
}
}
}
}
class Grid_app : App(Grid_view::class)
fun main() {
launch<Grid_app>()
}
cell 안에 circle 같은 도형도 그려 너을 수 있습니다.
'2023년 이전 > kotlin-TornadoFx' 카테고리의 다른 글
TornadoFx - Type-Safe CSS(1) (0) | 2019.10.31 |
---|---|
TornadoFX - Exception 문제 (0) | 2019.10.11 |
TornadoFx - Data Controls(1) (0) | 2019.10.10 |
TornadoFx - Builders for Basic Controls (0) | 2019.10.10 |
TornadoFx - How Builders Work (0) | 2019.10.10 |