首页 > 解决方案 > 在 JavaFx 应用程序中未正确显示 Swing 内容

问题描述

我目前正在开发 JavaFx 应用程序。Fx 应该只负责 UI 内容,而相当复杂的功能位于另一个已经完成的项目中,该项目是使用 Swing 创建的。为此,我使用 Scenebuilder 构建了一个 FXML,然后将多个 Swing 面板传递到单独的 SwingNode 中,并将 SwingNode 传递到 TabPane 的不同选项卡中(全部在我的 Application 类的 start() 方法中完成)。启动程序后,一切看起来都很好,Swing 和 Fx 内容显示正确,功能也正常工作。但是,当手动调整应用程序窗口的大小时,SwingNode 内容行为异常,有时选项卡保持为空,有时只绘制节点的一部分,有时它只是显示完全黑色。

现在,实际启动的程序是“旧”的 Swing 项目,它在某些时候使用 Platform.startup() 来启动 FX 应用程序。出于功能原因,这是必要的。那时的 Swing 面板被传递到位于 Fx 项目中的 SwingNodes。

我试图通过在窗口调整大小上不断设置 SwingNode-Content 来“更新” SwingNodes。我还尝试重新绘制 Swing 内容。两种尝试都没有成功。

我错过了什么?为什么 SwingNode 内容不与窗口的其余部分一起调整大小?Swing 内容是否可能太大而无法正常运行?还是可能存在一些多线程问题?

我知道如果没有任何代码示例,这个问题可能很难理解。我目前正在创建两个项目的简约版本,以重现我的问题,并在完成后立即更新。

编辑:我相信我能够重现该问题并尝试将所有内容包括在下面。fx被传递给swingBuildPath,但不是相反。运行时swing会打开一个 FX 窗口,其中包含三个选项卡,所有选项卡都充满了 SwingNode。但是,当用户调整此窗口的大小时,只有活动选项卡的 SwingNode 才能正确重新绘制。其他两个选项卡仍然包含节点,但是元素只有在鼠标悬停在它们上方时才会重新出现 - 这不适用于标签。我已经尝试在 SwingNodes 上使用重绘,但到目前为止没有成功,所以我选择不在这里包含它。

第二次编辑:删除了 FXML 和 FXML 控制器类,以使问题更小一些。FXML 只是一个简单的 TabPane,在 SceneBuilder 中内置了 3 个选项卡,控制器仅包含 3 个选项卡的 Getter。

调整大小并将鼠标悬停在 10 个按钮中的 3 个上后的选项卡 2

ProjectExplorer 中 Fx 项目的结构

ProjectExplorer 中 Swing 项目的结构

该项目fx包含MainFx扩展应用程序的类和DebugWindowControllerFXML 文件的控制器。还有一个 由项目中MainInterface的类实现的接口Mainswing

班级MainFx

package controllers;

import interfaces.MainInterface;
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class MainFx extends Application {

  private DebugWindowController debugWindowController;
  private AnchorPane            mainRoot;
  private final SwingNode       swingNode1    = new SwingNode();
  private final SwingNode       swingNode2    = new SwingNode();
  private final SwingNode       swingNode3    = new SwingNode();
  private MainInterface         mainInterface = null;



  @Override
  public void start(Stage primaryStage) {

    try {

      FXMLLoader debugWindowLoader = new FXMLLoader(getClass().getResource("/view/DebugWindow.fxml"));
      mainRoot = debugWindowLoader.load();
      debugWindowController = debugWindowLoader.getController();

      Scene scene1 = new Scene(mainRoot);

      fillFxTabPane();

      primaryStage.setScene(scene1);
      primaryStage.show();

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private void fillFxTabPane() {
    swingNode1.setContent(mainInterface.getPanel1());
    swingNode2.setContent(mainInterface.getPanel2());
    swingNode3.setContent(mainInterface.getPanel3());

    debugWindowController.getTab1().setContent(swingNode1);
    debugWindowController.getTab2().setContent(swingNode2);
    debugWindowController.getTab3().setContent(swingNode3);
  }

  public MainInterface getMainInterface() {
    return mainInterface;
  }

  public void setMainInterface(MainInterface mainInterface) {
    this.mainInterface = mainInterface;
  }

}

界面MainInterface

package interfaces;

import javax.swing.JComponent;

public interface MainInterface {


  JComponent getPanel1();

  JComponent getPanel2();

  JComponent getPanel3();

}

该项目swing仅包含一个类,其中包含用于启动程序的 main() 方法。班级Main

package swing;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

import controllers.MainFx;
import interfaces.MainInterface;
import javafx.application.Platform;
import javafx.stage.Stage;


public class Main implements MainInterface {

  private JPanel panel1;
  private JPanel panel2;
  private JPanel panel3;


  public Main() {

    panel1 = new JPanel();
    JLabel label1 = new JLabel("Panel1");
    panel1.add(label1);
    for (int i = 0; i < 10; i++) {
      JButton button = new JButton("B" + (i + 1));
      panel1.add(button);
    }

    panel2 = new JPanel();
    JLabel label2 = new JLabel("Panel2");
    panel2.add(label2);
    for (int i = 0; i < 10; i++) {
      JButton button = new JButton("B" + (i + 1));
      panel2.add(button);
    }

    panel3 = new JPanel();
    JLabel label3 = new JLabel("Panel3");
    panel3.add(label3);
    for (int i = 0; i < 10; i++) {
      JButton button = new JButton("B" + (i + 1));
      panel3.add(button);
    }

    MainFx mainFx = new MainFx();

    mainFx.setMainInterface(this);
    Platform.startup(() -> {// launch JavaFx application

      Stage stage = new Stage();
      try {
        mainFx.start(stage);
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    });

  }

  public static void main(String[] args) {

    Main main = new Main();

  }

  @Override
  public JComponent getPanel1() {
    return panel1;
  }

  @Override
  public JComponent getPanel2() {
    return panel2;
  }

  @Override
  public JComponent getPanel3() {
    return panel3;
  }
}

标签: javaswingjavafx

解决方案


推荐阅读