2

我正在使用 swing 显示多个 javafx Tableview,每个都嵌入(感谢 JFXPanel)在一个 swingTabbedPane

我以scala方式使用oracle doc中描述的众所周知的模式:

implicit def fun2Run[T](x: ⇒ T) = new Runnable {
    def run = x
  }

  def myTabbedScene():Scene = {
    val root = new StackPane
    root.getChildren.add(new Label("Hello world!"))
    new Scene(root, 300, 300)
  }

  def initFxPanel(fxPanel: JFXPanel, s: ⇒ Scene) = {
    fxPanel.setScene(s)
  }

  def initSwingGui(panel: PluginPanel) = {
    val fxPanel = new JFXPanel()
   // code to add panel to JPanel
    panel.peer.add(fxPanel)
    Platform runLater initFxPanel(fxPanel,myTabbedScene())
  }

  val jfxSwingPanel = new PluginPanel("wrap 2") {
    var jtemp = new JPanel()
    contents += jtemp
  }

  SwingUtilities invokeLater initSwingGui(jfxSwingPanel)

每次用户打开新的摆动选项卡时都会执行此代码(只有场景方法不同),但我不确定这是在这种情况下管理线程的最佳方法:-/

当我关闭或打开选项卡时,我的应用程序中有一些不连贯的状态,并且在显示期间出现错误。

我的用例的一个例子,以及一些链接的问题:

  • 我打开第一个选项卡 J1,调用 runlater,我的场景在选项卡中显示没有问题。

  • 我打开第二个选项卡 J2,在 javafx 线程上调用一个新的 runlater,

  • 我切换到标签 J1,我的标签中的显示如何刷新?向主线程启动隐式runnable操作以使这成为可能?javafx如何识别刷新的好标签?如果我有一个启动某些动作的按钮,我会runlater()在 javafx 主线程上启动一个动作,该线程调度?

更新:

我找到了一个可以帮助读者了解这一点的代码源,您可以revalidate()或/和repaint()您的摆动面板(此处_contentpane)包含您的jfxPanel

   SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
    _contentPane.add(_jfxPanel); 
    _contentPane.revalidate(); 
    _contentPane.repaint(); }});
  • 我关闭第一个选项卡 J1,javafx 自动关闭/垃圾关联的 javafx 资源?

我有多个其他一般性问题:

  • 当 javafx 应用程序主线程从 swing 中的不同 jfxpanel 到达时,它们如何管理这个多个 runlater() 调用?

  • 当用户关闭选项卡时,如何正确关闭与我的 jfxpanel 关联的资源(不使用 exit() Platform 方法关闭主 javafx 线程)?如果我销毁 JFXPanel,用于显示的 javafx 资源是否被释放?

  • 使用任务来管理我的线程可以解决我的问题吗?

我的问题可能很幼稚,但我从 gui 构建开始,我很难理解 javafx 如何在不同的嵌入式面板上管理场景。

4

1 回答 1

3

当 javafx 应用程序线程从 swing 中的不同 jfxpanel 到达时,它们如何管理这个多个 runlater() 调用?

从 Platform.runLater javadoc:

在未来某个未指定的时间在 JavaFX 应用程序线程上运行指定的 Runnable。此方法可以从任何线程调用,它将 Runnable 发布到事件队列,然后立即返回给调用者。Runnables 按照它们发布的顺序执行。传递给 runLater 方法的 runnable 将在传递给后续调用 runLater 的任何 Runnable 之前执行。

更远:

当用户关闭选项卡时,如何正确关闭执行我的 jfxpanel 的线程(不关闭主 javafx 线程)?

目前尚不清楚您指的是哪个线程。一般来说,在集成 JavaFX 和 Swing 时,只需要关注两个线程 - Swing 调度线程和 JavaFX 应用程序线程 - 这两个线程都应该由各自的底层框架管理,您不需要显式关闭。您不需要任何其他线程,除非您尝试执行不应在其中任何一个线程上执行的操作(例如高度 CPU 密集型任务或远程 I/O) - 从您的示例代码中不会出现就是这样。

使用任务来管理我的线程可以解决我的问题吗?

除非您对这样的事情有特殊需求,否则这样的解决方案可能会使您的情况变得更加复杂而不是改善它。

我关闭第一个选项卡 J1,javafx 自动关闭/垃圾关联的 javafx 资源?

如果您不保留对相关 jfxpanel 中任何资源的引用,那么 Java 虚拟机可以对 jfxpanel 和与之相关的资源进行垃圾收集——这只是标准的 Java 垃圾收集技术,这里没什么特别的。

我切换到标签 J1,我的标签中的显示如何刷新?向主线程启动隐式可运行操作以使这成为可能?

听起来是个坏主意(Java 术语中的主线程是用于启动 Java 的 main 函数的线程,根本不参与 GUI 编程)。您可能希望通过提交您的可运行刷新请求,Platform.runLater()以便它将在 JavaFX 应用程序线程上执行。

javafx如何识别刷新的好标签?

您在每个摆动选项卡中都有一个 JavaFX JFXPanel,并且每个摆动选项卡都知道它具有哪个 JFXPanel,因此当您调用 Platform.runLater 以刷新特定面板时,将(最终)引用传递给要使用的 JFXPanel。这是一些没有任何语言的伪代码来说明这个概念:

on swing tab change event
  final JFXPanel curPanel = tab.getJFXPanel()
  Platform.runLater() {
    // update curPanel here...
  }

如果我有一个启动某些操作的按钮,我会在 javafx 主线程上启动一个 runlater() 操作,它调度?

从本质上讲,我认为您在这里是正确的,我只是重写您的问题以澄清一些术语-假设它是一个摆动按钮,并且在对摆动按钮执行操作时,您调用Platform.runLater,然后在runLater 调用最终将在 JavaFX 应用程序线程上执行。


其他问题我无法回答,因为我在 Scala 中不够流利,无法提供合理的答案。

老实说,如果您刚刚开始构建 GUI,那么我主动提出的建议是使用 Java 而不是 Scala,并坚持使用 Swing 或 JavaFX,但在您真正熟悉 GUI 构建过程之前不要将它们混合在一起 - 否则会有在集成过程中您可能会遇到太多的陷阱和陷阱,很少有人能够帮助您。

于 2013-01-21T22:28:33.257 回答