gpt4 book ai didi

scala - 创建自定义 ScalaFX 控件

转载 作者:行者123 更新时间:2023-12-01 12:40:26 24 4
gpt4 key购买 nike

创建自定义 ScalaFX 控件的正确方法到底是什么?我来自 Swing 和 Scala Swing,其中自定义组件只是通过扩展 Component 来创建的。或 Panel .但是当我尝试扩展 ScalaFX 的 Control , 我无法在没有 JavaFX Control 的情况下扩展它代表。我是否应该通过扩展基本 JavFX 类而不是 ScalaFX 类来创建自定义 ScalaFX 组件?

最佳答案

一般来说,你会想要:

  • 创建自定义 JavaFX 控件。
  • 然后可以选择在与默认模型相同的模型上创建自定义 ScalaFX 包装器。请注意,即使没有特定的 ScalaFX 包装器,一些 ScalaFX 功能(如绑定(bind))也应该可以正常工作 - 你可以看到 some examples here .

  • 要创建自定义 JavaFX 控件,首先要检查的资源是 this Oracle tutorial , 但是 this blog post走得更远。像 ControlsFX 这样的开源项目和 JFXtras提供大量控件示例。

    显然,所有这些资源都展示了如何在 Java 中做到这一点。我看不出为什么你不能在 Scala 中做到这一点(只要你使用 JavaFX 类而不是 ScalaFX 类)——但我找不到任何相关文档,所以我猜它可能是在 Java 中创建控件更安全。

    编辑:我放了 on github带有 ScalaFX 包装类的简单自定义 JavaFX 控件的两个示例。一个版本, YieldingSlider , 是扩展 Slider 的单个 Java 类。类(class);另一个版本, FxmlYieldingSlider , 基本上是一样的,但是它展示了如何用一个 FXML 文件和一个 Controller 类来构造一个控件。请注意,从此项目构建的 JAR 文件可以在 Scene Builder 2.0 中导入,以便 Scene Builder 可以使用 <YieldingSlider><FxmlYieldingSlider> FXML 中的控件。

    这是简单版本的样子。

    JavaFX 控件:
    package customjavafx.scene.control;

    import javafx.scene.control.Slider;
    import javafx.scene.input.MouseEvent;

    public class YieldingSlider extends Slider {

    public YieldingSlider() {
    addEventFilter(MouseEvent.MOUSE_PRESSED, event -> lastTimeMousePressed = System.currentTimeMillis());
    }

    public YieldingSlider(final double min, final double max, final double value) {
    this();
    setMin(min);
    setMax(max);
    setValue(value);
    }

    private long lastTimeMousePressed = 0;

    public boolean mouseWasPressedWithinLast(final long t) {
    return (System.currentTimeMillis() - lastTimeMousePressed) <= t;
    }
    }

    ScalaFX 包装器:
    package customscalafx.scene.control

    import scala.language.implicitConversions
    import customjavafx.scene.{control => jfxsc}
    import scalafx.scene.control.Slider

    object YieldingSlider {
    implicit def sfxSlider2jfx(v: YieldingSlider) = v.delegate
    }

    class YieldingSlider(override val delegate: jfxsc.YieldingSlider = new jfxsc.YieldingSlider) extends Slider {

    /** Constructs a Slider control with the specified slider min, max and current value values. */
    def this(min: Double, max: Double, value: Double) {
    this(new jfxsc.YieldingSlider(min, max, value))
    }
    }

    可用于 FXML:
    <?xml version="1.0" encoding="UTF-8"?>

    <?import customjavafx.scene.control.*?>
    <?import java.lang.*?>
    <?import javafx.scene.layout.*?>

    <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <children>
    <YieldingSlider AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
    </children>
    </AnchorPane>

    或者在 ScalaFX DSL 中:
    package guilgaly.fxtest.mp3player

    import customscalafx.scene.control.YieldingSlider

    import scalafx.application.JFXApp
    import scalafx.scene.Scene

    object TestApp extends JFXApp {
    stage = new JFXApp.PrimaryStage {
    scene = new Scene {
    content = new YieldingSlider
    }
    }
    }

    最后,请注意,如果您将其与 ScalaFXML 一起使用,它将无法正确注入(inject) Controller ,因为 ScalaFXML 会查找包以 scalafx.* 开头的类。 (并期望在同一个包中对应的 JavaFX 类,但盯着 javafx.* )。但是,如果您使用从 javafx.* 开始的包,您无法在 Scene Builder 中导入您的控件。我的解决方案是在 ScalaFXML 代码中添加一个丑陋的 hack,以便它处理 customscalafx.*喜欢 scalafx.* .但这只是在使用 ScalaFXML 时需要考虑的问题。

    编辑 2:当我在这里时,这是用Scala而不是Java编写的相同JavaFX控件。它的工作原理相同,如果需要,可以将其包装在类似的 ScalaFX 包装器中。
    package customjavafx.scene.control

    import javafx.event.EventHandler
    import javafx.scene.control.Slider
    import javafx.scene.input.MouseEvent

    class ScalaYieldingSlider extends Slider{
    def this(min: Double, max: Double, value: Double) = {
    this()
    setMin(min)
    setMax(max)
    setValue(value)
    }
    // Support for Java 8 SAMs (lambdas) is still experimental in Scala 2.11.
    // I used the old-school anonymous class instead.
    addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler[MouseEvent] {
    def handle(event: MouseEvent): Unit = lastTimeMousePressed = System.currentTimeMillis
    })

    private var lastTimeMousePressed: Long = 0

    def mouseWasPressedWithinLast(t: Long): Boolean =
    (System.currentTimeMillis - lastTimeMousePressed) <= t
    }

    关于scala - 创建自定义 ScalaFX 控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25401094/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com