Kotlin 制作我自己的按钮类

Kotlin 制作我自己的按钮类,kotlin,tornadofx,Kotlin,Tornadofx,我正在使用TornadoFX框架和Kotlin创建一个简单的桌面应用程序,让用户点击一个按钮,选择一个USFM文件,并将该USFM文件的内容放入一个文本区域。我已经具备了基本的功能,但我想通过分离按钮的逻辑来提高代码的层次。目前,我的唯一视图定义了单击我的按钮时要执行的操作的逻辑。代码如下所示: import tornadofx.* import javafx.scene.layout.BorderPane import javafx.stage.FileChooser import javaf

我正在使用TornadoFX框架和Kotlin创建一个简单的桌面应用程序,让用户点击一个按钮,选择一个USFM文件,并将该USFM文件的内容放入一个文本区域。我已经具备了基本的功能,但我想通过分离按钮的逻辑来提高代码的层次。目前,我的唯一视图定义了单击我的按钮时要执行的操作的逻辑。代码如下所示:

import tornadofx.*
import javafx.scene.layout.BorderPane
import javafx.stage.FileChooser
import javafx.scene.control.Button
import javafx.scene.control.Label
import javafx.scene.control.TextArea
import java.io.File

class AppView : View() {
    override val root: BorderPane by fxml()

    val chooseFile: Button by fxid<Button>()
    val fileName: Label by fxid<Label>()
    val textArea: TextArea by fxid<TextArea>()
    lateinit var fileChosen: File
    init {
        title = "USFM Viewer"
        root.lookup(".button").setOnMouseClicked {
            var fileFilter = arrayOf(FileChooser.ExtensionFilter("USFM files", "*.usfm"))
            fileChosen = chooseFile("Select a USFM File", fileFilter, FileChooserMode.Single)[0]
            fileName.text = fileChosen.name
            val fileParser = USFMFileParser(fileChosen)
            val printout = fileParser.readFile(fileChosen)
            textArea.text = printout.joinToString()
        }

    }
}
class AppView : View("USFM Viewer") {
    override val root: BorderPane by fxml()

    val chooseFile: Button by fxid<Button>()
    val textArea: TextArea by fxid<TextArea>()

    init {
        chooseFile.loadFile(textArea.textProperty(), filters = arrayOf(FileChooser.ExtensionFilter("USFM File", "*.usfm")))
    }
}
import.fx*
导入javafx.scene.layout.BorderPane
导入javafx.stage.FileChooser
导入javafx.scene.control.Button
导入javafx.scene.control.Label
导入javafx.scene.control.TextArea
导入java.io.xml文件
类AppView:View(){
通过fxml()覆盖val root:BorderPane
val chooseFile:Button by fxid()
val fileName:Label by fxid()
val textArea:textArea by fxid()
lateinit var FILESELECTED:文件
初始化{
title=“USFM查看器”
root.lookup(“.button”)。setOnMouseClicked{
var fileFilter=arrayOf(FileChooser.ExtensionFilter(“USFM文件”,“*.USFM”))
FileSelected=chooseFile(“选择USFM文件”、fileFilter、FileChooserMode.Single)[0]
fileName.text=fileselected.name
val fileParser=USFMFileParser(fileselected)
val printout=fileParser.readFile(fileselected)
textArea.text=printout.joinToString()
}
}
}
我最初的计划是创建自己的button类,该类继承自button类,并使用自己的方法重写或初始化以处理单击事件。目标是在我的视图文件中简单地声明按钮,而不必为它定义额外的逻辑。我似乎在努力争取这份工作

这是我自定义按钮类的原型:

import javafx.scene.control.Button
import javafx.stage.FileChooser
import tornadofx.*
import java.io.File

class ChooseFileButton: Button(){
    val fileFilter = arrayOf(FileChooser.ExtensionFilter("USFM File", "*.usfm"))
    val files: List<File>
        get() = chooseFile("Select a USFM File", fileFilter, FileChooserMode.Single)
    init {
        action { println(this.files[0].name) }
    }
}
import javafx.scene.control.Button
导入javafx.stage.FileChooser
导入tornadofx*
导入java.io.xml文件
类ChooseFileButton:Button(){
val fileFilter=arrayOf(FileChooser.ExtensionFilter(“USFM文件”,“*.USFM”))
val文件:列表
get()=chooseFile(“选择一个USFM文件”、fileFilter、FileChooserMode.Single)
初始化{
操作{println(this.files[0].name)}
}
}
此外,这里是我的FXML文件,用于提供有关我的阶段中元素的更多上下文:

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>

<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.FlowPane?>
<BorderPane id="appview"
            xmlns="http://javafx.com/javafx/8.0.40"
            xmlns:fx="http://javafx.com/fxml/1"
            prefHeight="635"
            prefWidth="500">
    <top>
        <FlowPane>
            <Button fx:id="chooseFile" id="chooseFile" text="Choose File..." />
            <Label fx:id="fileName" id="fileName" text="No File Chosen"/>
        </FlowPane>
    </top>
    <center>
        <ScrollPane>
            <TextArea fx:id="textArea" id="textArea"></TextArea>
        </ScrollPane>
    </center>
</BorderPane>


对于如何将按钮逻辑从视图中分离出来,是否有任何提示、建议、链接等?这可能吗?

不需要为此创建按钮子类。只需在
ButtonBase
上创建一个扩展函数,按照您想要的方式配置按钮,并为每个按钮调用该函数一次。您还应该考虑使用FIX类型的安全生成器来跳出FXML,这样会更方便,更不用说类型安全了。 下面是这样一个函数的示例,它允许您指定解析器、筛选并将文件加载到目标字符串属性中。还有一个默认解析器,它只按原样加载文件

fun ButtonBase.loadFile(target: Property<String>,
                        parser: (File) -> String = { Files.readAllBytes(it.toPath()).toString(StandardCharsets.UTF_8) },
                        filters: Array<FileChooser.ExtensionFilter>) {
    action {
        chooseFile(text, filters, FileChooserMode.Single).firstOrNull()?.let {
            target.value = parser.invoke(it)
        }
    }
}
如果您真的想坚持使用FXML(也许您只想键入stuff:),您可以这样称呼它:

import tornadofx.*
import javafx.scene.layout.BorderPane
import javafx.stage.FileChooser
import javafx.scene.control.Button
import javafx.scene.control.Label
import javafx.scene.control.TextArea
import java.io.File

class AppView : View() {
    override val root: BorderPane by fxml()

    val chooseFile: Button by fxid<Button>()
    val fileName: Label by fxid<Label>()
    val textArea: TextArea by fxid<TextArea>()
    lateinit var fileChosen: File
    init {
        title = "USFM Viewer"
        root.lookup(".button").setOnMouseClicked {
            var fileFilter = arrayOf(FileChooser.ExtensionFilter("USFM files", "*.usfm"))
            fileChosen = chooseFile("Select a USFM File", fileFilter, FileChooserMode.Single)[0]
            fileName.text = fileChosen.name
            val fileParser = USFMFileParser(fileChosen)
            val printout = fileParser.readFile(fileChosen)
            textArea.text = printout.joinToString()
        }

    }
}
class AppView : View("USFM Viewer") {
    override val root: BorderPane by fxml()

    val chooseFile: Button by fxid<Button>()
    val textArea: TextArea by fxid<TextArea>()

    init {
        chooseFile.loadFile(textArea.textProperty(), filters = arrayOf(FileChooser.ExtensionFilter("USFM File", "*.usfm")))
    }
}
class AppView:View(“USFM查看器”){
通过fxml()覆盖val root:BorderPane
val chooseFile:Button by fxid()
val textArea:textArea by fxid()
初始化{
chooseFile.loadFile(textArea.textProperty(),filters=arrayOf(FileChooser.ExtensionFilter(“USFM文件”,“*.USFM”))
}
}
loadFile
功能可以按您喜欢的任何方式展开,例如通过返回所选文件、为文件选择器对话框指定单独的标题等


另一个提示:在示例代码中,您使用fxml()委托找到了按钮,但随后又进行了另一次
查找
以再次找到按钮。你应该重新使用你已经找到的按钮。

非常感谢你,伙计。这非常有用。我对视图做了一些修改,以获得我喜欢的方式,并将文本区域中的文本设置为文件的内容。再次感谢您的帮助:))