无法将回调或updateItem代码放置到JavaFX / Kotlin中的自定义TableColumn

时间:2018-12-28 06:42:59

标签: javafx kotlin

我想在单击newButton时将选中的复选框更改为未选中。 因此,在handelNew函数上,我为Item.select分配了错误的值。

当我运行handleNew函数时,它将表中的每个Item.select设置为false,但是该复选框仍显示为选中状态。

通过搜索,我了解我必须添加回调代码或将updateItem覆盖到cellFactory或以下项中:

这些答案似乎对我有帮助,但是每个代码都是用Java编写的,因此我不明白应在哪里放置Call​​back或updateItem函数。

我试图将Java代码转换为Kotlin,但是转换后的代码仍然让我感到困惑。

我应该在哪里添加Callback / updateItem函数,以及如何对其进行更改?

我的环境: * JavaFX 11 * JDK 11

完整的源代码存储库:https://github.com/QuietJoon/StudyKotlin-JavaFX

Item.kt

import javafx.beans.property.*

class Item(isSelected: Boolean, groupID: GroupID, name: String){
    val select = SimpleBooleanProperty()
    private val name = SimpleStringProperty()
    private val groupID = SimpleIntegerProperty()

    var isSelected:Boolean
        get() = select.get()
        set(on) = select.set(on)

    init{
        setGroupID(groupID)
        setName(name)
        this.isSelected = isSelected
    }

    fun nameProperty():StringProperty = this.name    
    fun getName():String = this.nameProperty().get()    
    fun setName(name:String) = this.nameProperty().set(name)    
    fun groupIDProperty():IntegerProperty = this.groupID    
    fun getGroupID():GroupID = this.groupIDProperty().get()    
    fun setGroupID(groupID:GroupID) = this.groupIDProperty().set(groupID)    
    override fun toString():String = getGroupID().toString() + getName()
}

typealias GroupID = Int

GUI.kt

import java.util.*

import javafx.application.Application
import javafx.collections.FXCollections
import javafx.event.ActionEvent
import javafx.event.EventHandler
import javafx.fxml.FXMLLoader
import javafx.scene.Parent
import javafx.scene.Scene
import javafx.scene.control.*
import javafx.scene.input.TransferMode
import javafx.scene.paint.Paint
import javafx.scene.shape.Rectangle
import javafx.stage.Stage

class TAB : Application() {

    private var selectAllCheckBox: CheckBox? = null

    override fun start(primaryStage: Stage) {
        primaryStage.title = "Study Tab layout!"
        primaryStage.isAlwaysOnTop = true
        val fxml = javaClass.getResource("fxml/Tab.fxml")
        val root: Parent = FXMLLoader.load(fxml)
        val scene = Scene(root)
        val itemTable = root.lookup("#TableView1") as TableView<Item>
        val newButton = root.lookup("#NewButton") as Button

        selectAllCheckBox = CheckBox()

        scene.onDragOver = EventHandler { event ->
            val db = event.dragboard
            if (db.hasFiles()) {
                event.acceptTransferModes(TransferMode.COPY)
            } else {
                event.consume()
            }
        }

        scene.onDragDropped = EventHandler { event ->
            val db = event.dragboard
            var success = false

            if (db.hasFiles()) {
                success = true

                // Session #1
                val itemList = db.files.map {
                    val anItem = Item(false,0,it.toString())
                    anItem.select.addListener{ ov,old_val,new_val ->
                        println(anItem.getName() + "'s CB status changed from '"
                        + old_val + "' to '" + new_val + "'.")
                    }
                    anItem
                }

                itemTable.items = FXCollections.observableArrayList(itemList)

                println("End a case")
            }
            event.isDropCompleted = success
            event.consume()
        }

        newButton.setOnAction { event -> handleNew(event,itemTable) }

        primaryStage.scene = scene
        primaryStage.show()
    }

    private fun handleNew(e: ActionEvent, itemTable: TableView<Item>) {
        val groupIDSet: SortedSet<Int> = sortedSetOf()

        for (anItem in itemTable.items) {
            if (anItem.isSelected)
                println(anItem.getName())
            else
                groupIDSet.add(anItem.getGroupID())
        }
        var newID = 0
        for ( idx in groupIDSet ) {
            if (newID < idx) break
            newID++
        }
        for (anItem in itemTable.items) {
            if (anItem.isSelected)
                anItem.setGroupID(newID)
            // TODO: [BUG] This does not update GUI
            anItem.isSelected = false
        }
    }
}

util / CheckBoxColumn.kt

package util
// Read from https://takeda-san.hatenablog.com/entry/2017/07/25/232840

import Item
import javafx.beans.property.SimpleBooleanProperty
import javafx.event.Event
import javafx.scene.control.TableColumn
import javafx.scene.control.cell.CheckBoxTableCell
import javafx.scene.control.cell.PropertyValueFactory
import javafx.scene.input.MouseButton
import javafx.scene.input.MouseEvent


class CheckBoxColumn : TableColumn<Item, Boolean>() {
    init {
        this.cellValueFactory = PropertyValueFactory<Item, Boolean>("select")

        this.setCellFactory { column ->
            val cell = CheckBoxTableCell<Item, Boolean> { index ->
                val selected = SimpleBooleanProperty(
                    this.tableView.items[index].isSelected
                )
                selected.addListener { _, _, n ->
                    this.tableView.items[index].isSelected = n
                    this.tableView.selectionModel.select(index)

                    Event.fireEvent(
                        column.tableView, MouseEvent(
                            MouseEvent.MOUSE_CLICKED, 0.0, 0.0, 0.0, 0.0,
                            MouseButton.PRIMARY, 1, true, true, true, true, true, true, true, true, true, true, null
                        )
                    )
                }
                selected
            }
            cell
        }
    }
}

Tab.fxml

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Rectangle?>
<?import util.CheckBoxColumn?>

<AnchorPane prefHeight="800.0" prefWidth="1600.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <TabPane prefHeight="800.0" prefWidth="1600.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <tabs>
          <Tab text="Session #1">
              <content>
                  <AnchorPane fx:id="TabSession1" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                      <children>
                          <TableView fx:id="TableView1" editable="true" layoutX="16.0" layoutY="16.0" prefHeight="313.0" prefWidth="565.0" AnchorPane.bottomAnchor="64.0" AnchorPane.leftAnchor="16.0" AnchorPane.rightAnchor="16.0" AnchorPane.topAnchor="16.0">
                              <columns>
                                  <CheckBoxColumn minWidth="64.0" text="Check" />
                                  <TableColumn minWidth="64.0" text="Group ID">
                                      <cellValueFactory>
                                          <PropertyValueFactory property="groupID" />
                                      </cellValueFactory>
                                  </TableColumn>
                                  <TableColumn prefWidth="256.0" text="Name">
                                      <cellValueFactory>
                                          <PropertyValueFactory property="name" />
                                      </cellValueFactory>
                                  </TableColumn>
                              </columns>
                          </TableView>
                          <Button fx:id="NewButton" layoutX="16.0" layoutY="384.0" mnemonicParsing="false" text="Make New" AnchorPane.bottomAnchor="16.0" AnchorPane.leftAnchor="16.0" />
                          <Button fx:id="GoButton" layoutX="1543.0" layoutY="731.0" mnemonicParsing="false" text="Go" AnchorPane.bottomAnchor="16.0" AnchorPane.rightAnchor="16.0" />
                      </children>
                  </AnchorPane>
              </content>
          </Tab>
          <Tab text="Session #2">
              <content>
                  <AnchorPane fx:id="TabSession2" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                      <Rectangle fx:id="StatusIndicator" arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="32.0" layoutX="100.0" layoutY="10.0" stroke="BLACK" strokeType="INSIDE" width="256.0" AnchorPane.leftAnchor="16.0" AnchorPane.topAnchor="16.0" />
                      <Label fx:id="FilePathsLabel" layoutX="100.0" layoutY="60.0" text="Nothing" AnchorPane.leftAnchor="16.0" AnchorPane.topAnchor="64.0" />
                  </AnchorPane>
              </content>
          </Tab>
        </tabs>
      </TabPane>
   </children>
</AnchorPane>

0 个答案:

没有答案