ScalaFX - 如何使用方法获取场景的标题

2024-01-04

我正在使用 ScalaFX 并尝试了解它是如何工作的。作为一个实验(不是我在生产中要做的),我想要一种获取窗口标题的方法。

这是我的 Graph.scala 文件:

package graphing

import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.scene.paint.Color

class Graph {
  val app = new JFXApp {
    stage = new JFXApp.PrimaryStage {
      title = "First GUI"
      scene = new Scene {
        fill = Color.Coral
      }
    }
  }

  def getTitle() = {
    app.stage.getTitle
  }

  def generateChart(args: Array[String]) = app.main(args)
}

这是我使用该 Graph 类的驱动程序对象:

package graphing

import graphing.Graph

object Driver extends App {
  val graph = new Graph

println(graph.getTitle())

  graph.generateChart(args)
}

但是,由于该行,这不起作用

println(graph.getTitle())

The error that is thrown: enter image description here

有人可以解释一下发生了什么事以及我如何在这里实现我的目标吗?


这里的问题涉及JavaFX(因此,ScalaFX)初始化。

正在初始化JavaFX是一项复杂的业务。 (确实,我最近才知道这是甚至更复杂比我最初相信的要多。参考最近的这个答案 https://stackoverflow.com/a/62001855/2593574在这里堆栈溢出了解更多背景。幸运的是,您的问题更容易解决。)

ScalaFX简化JavaFX初始化很大,但要求JFXApp特征被用作定义的一部分object.

JFXApp包含一个main方法,其中must是您申请的起点;正是这个方法解决了初始化的复杂性JavaFX为你。

在你的例子中,你有你的Driver对象扩展scala.App, 就是这样App的(因此,Driver's) main方法成为您自己的应用程序的起点。这对于普通人来说很好命令行界面 (CLI) 应用程序,但不能与ScalaFX/JavaFX应用程序无需太多额外的复杂性。

在你的代码中,JFXApp's main方法永远不会执行,因为它被定义为类成员,所以它不是main的方法Scala object,因此不是自动执行的候选者JVM。您确实可以从您的Graph.generateChart()方法,但该方法本身不会被调用,直到after你试图获得场景的标题,因此NPE因为阶段尚未初始化。

如果你把graph.generateChart(args) call before the println(graph.getTitle())陈述?这能解决问题吗?可悲的是没有。

这就是为什么...

JFXApp还执行另一位magic:它执行其构造代码object(以及对于任何其他classes 由该对象扩展,但不用于扩展traits) 在JavaFX 应用程序线程 (JAT)。这很重要:只有在JAT可以直接与JavaFX(即使通过ScalaFX)。如果您尝试执行JavaFX在任何其他线程(包括应用程序的主线程)上进行操作,那么您将得到异常。

(This magic依赖于已弃用的Scala trait, scala.DelayedInit,已从库中删除斯卡拉3.0, aka Dotty,因此将来需要不同的机制。不过,值得一读文档 https://www.scala-lang.org/api/current/scala/DelayedInit.html了解该特征以了解更多背景。)

所以,当Driver的构造代码调用graph.generateChart(args),它导致JavaFX要初始化,启动JAT,并执行Graph的构造代码。然而,到了那时Driver的构造函数调用println(graph.getTitle()),仍然在主线程上执行,有两个问题:

  1. Graph的构造代码可能已执行,也可能未执行,因为它是在不同的线程上执行的。 (这个问题被称为竞争条件,因为主线程尝试调用之间存在竞争println(graph.getTitle()),以及JAT尝试初始化graph例如。)你可能会在某些情况下赢得比赛,但你也会经常失败。
  2. 您正在尝试与以下人员互动JavaFX从主线程,而不是从JAT.

以下是为您的应用程序工作推荐的方法:

package graphing

import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.scene.paint.Color

object GraphDriver
extends JFXApp {

  // This executes at program startup, automatically, on the JAT.
  stage = new JFXApp.PrimaryStage {
    title = "First GUI"
    scene = new Scene {
      fill = Color.Coral
    }
  }

  // Print the title. Works, because we're executing on the JAT. If we're NOT on the JAT,
  // Then getTitle() would need to be called via scalafx.application.Platform.runLater().
  println(getTitle())

  // Retrieve the title of the stage. Should equal "First GUI".
  //
  // It's guaranteed that "stage" will be initialized and valid when called.
  def getTitle() = stage.title.value
}

请注意,我已经结合了你的Graph类和Driver对象变成单个对象,GraphDriver。虽然我不确定您的应用程序在架构上需要是什么样子,但这对您来说应该是一个不错的起点。

另请注意scala.App根本没有被使用。

打电话时要小心GraphDriver.getTitle():此代码需要在JAT。执行可能在不同线程上运行的任何代码的标准解决方法是将其传递给by name to scalafx.application.Platform.runLater()。例如:

import scalafx.application.Platform

// ...
Platform.runLater(println(ObjectDriver.getTitle()))
// ...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ScalaFX - 如何使用方法获取场景的标题 的相关文章

  • JavaFX:使用常量字符串前缀绑定 StringProperty

    我对 JavaFX 中的绑定功能有疑问 我想要的是绑定 2 个字符串属性 但他们的价值观不应该是平等的 让我举个例子 我有一个 StringProperty 代表我的应用程序中最后打开的项目 该值类似于 C temp myProject p
  • 新式(“内联”)宏需要 scala.meta

    我刚刚更新到 scala meta 2 0 0 M1 和最新的 scala 2 12 3 现在宏不再编译 我所做的唯一更改是将元版本从 1 8 0 更改为 2 0 0 M1 错误 新式 内联 宏需要 scala meta 有谁知道是否有快速
  • Scala 集合不一致

    为什么 Scala Collections API 中的集合和列表之间缺乏一致性 例如 有不可变的 Set 但也有可变的 Set 如果我想使用后者 我可以简单地这样做 val set Set A set new A 但是 本身不存在可变列表
  • jquery UI datepicker - 禁用日期范围

    我正在努力让某些东西正常工作 我遇到了 未捕获的类型错误 无法读取未定义的属性 0 错误 如下所示 我不明白为什么 我正在尝试在度假别墅网站上使用 jQuery UI 日期选择器来指示可用性和季节 低 高等 我有一个作为 datePicke
  • Scala 中值类的隐式 Json 格式化程序

    我有许多值类组成了一个更大的对象案例类 final case class TopLevel foo Foo bar Bar final case class Foo foo String extends AnyVal final case
  • 如何抑制spark输出控制台中的“Stage 2===>”?

    我有数据帧并试图获取不同的计数并且能够成功获取不同的计数 但是每当 scala 程序执行时我都会收到此消息 Stage 2 gt 1 1 2 我如何在控制台中抑制特定的此消息 val countID dataDF select substr
  • 如何在两个类之间共享数据

    Question 有没有一种方法可以让两个类同时相互继承 背景 我目前正在开发一个 Socket Server 项目 在这个项目中 我有两个课程 一个Server类 以及一个GUI班级 他们的目的是不言自明的 但是 我显然需要让两个班级相互
  • 如何在 JavaFX 中对单选按钮的最大可选复选框进行限制?

    请看下面的图片 您就会了解我的应用程序的布局 我希望能够动态选择多少CheckBox 启用下拉菜单 是可选的 固定数量 我想用这 3 个人来实现这个目标RadioButton 在垂直模式下全部 4CheckBox必须选择 不少于 在混合模式
  • 模态对话框是如何实现的?

    很长一段时间我一直想知道模态对话框是如何实现的 让我以Qt为例 几乎所有的GUI工具包都有这个机制 在主事件循环中 调用一个槽 并在该槽中打开一个模式对话框 在对话框关闭之前 槽不会将控制返回到主事件循环 所以我认为主事件循环被阻塞并且变得
  • 如何隐藏其他选项卡的内容并仅显示所选选项卡的内容

    当我单击特定选项卡时 其他选项卡的内容应该隐藏 但它并没有隐藏 这是我所有的代码 function showStuff id if document getElementById id style display block documen
  • 不支持的身份验证令牌,仅当禁用身份验证时才允许 schema='none':{ schema='none' } - Neo4j 身份验证错误

    我正在尝试使用 neo4j spark connector 从 Spark 连接到 Neo4j 当我尝试连接到 Neo4j 时遇到身份验证问题org neo4j driver v1 exceptions AuthenticationExce
  • 如何在 Scala 中打印任何内容的列表?

    目前我有一个打印整数的方法 def printList args List Int Unit args foreach println 我如何修改它 使其足够灵活 可以打印任何内容的列表 您不需要专用的方法 所需的功能已经在集合类中 pri
  • JavaFX Integer Spinner (IntegerSpinnerValueFactory) 不会将值回绕到最小值

    我创建了一个带有值的整数微调器 min 5 max 15 and initialValue 12 and wrapAround true 一旦旋转器到达max 15 增量期间的值 而不是将值重置为min 5 正如它所说文档 https op
  • 错误:协变类型 A 出现在逆变位置

    我试图写一个不可变的Matrix A 班级 我希望该类是协变的A但是当我把 在 前面A编译器开始抱怨类中的某些操作 以下是我的相关子集Matrix类 实际类比以下子集大 5 倍左右 class Matrix A private val co
  • JavaFX 中具有自定义内容的 ListView

    How i can make custom ListView with JavaFx for my app I need HBox with image and 2 Labels for each line listView 您可以通过查看
  • 对 Scala Not Null 特征的库支持

    Notice 从 Scala 2 11 开始 NotNull已弃用 据我了解 如果您希望引用类型不可为空 则必须混合魔法NotNull特征 编译器会自动阻止你输入null 可以值在里面 看到这个邮件列表线程 http www nabble
  • Javafx 拖放 TabPane

    我 在 JavaFx 应用程序中 有一个带有不同选项卡的选项卡 我想实现拖放功能以将选项卡拖到舞台之外 这样它就可以生成一个新窗口 就像在 Google Chrome 中一样 谢谢您的帮助 您应该检查 Tom Schindl 在他的网站上显
  • Javafx过滤表视图

    我正在尝试使用文本字段来过滤表视图 我想要一个文本字段 txtSearch 来搜索 nhs 号码 名字 姓氏 和 分类类别 我尝试过在线实施各种解决方案 但没有运气 我对这一切仍然很陌生 所以如果问得不好 我深表歉意 任何帮助将不胜感激 我
  • JavaFX ImageView 未更新

    因此 我尝试将图像加载并保存到 imageView 中 其中图像的位置是通过文件浏览器选择的 我已经为此工作好几天了 如果我不能解决这个问题 我就会中风 我已经尝试了我能想到的一切 预先感谢您的帮助 UPDATED 这是我的主要课程 pub
  • GUI Java 程序 - 绘图程序

    我一直试图找出我的代码有什么问题 这个想法是创建一个小的 Paint 程序并具有红色 绿色 蓝色和透明按钮 我拥有我能想到的让它工作的一切 但无法弄清楚代码有什么问题 该程序打开 然后立即关闭 import java awt import

随机推荐