在SWT中嵌入JavaFX

By | 3月 12, 2017

登录面板是JavaFX,运行在SWT Shell里面。

image 

1. 无侵入式使用FXCanvas

在需要放JavaFX控件的地方,构造一个FXCanvas,然后放入JavaFX控件。

FXCanvas fxCanvas = new FXCanvas(swtComposite, SWT.NONE);
LoginPaneFx loginPane = new LoginPaneFx();
fxCanvas.setScene(new Scene(loginPane));

注意:

FXML文件的根节点,要使用<fx:root/>格式,LoginPaneFx必须继承FXML根节点的对象(此处是GridPane)。代码中调用FXMLLoader的setRoot()方法,完成LoginPaneFx和FXML根节点的绑定。

<fx:root type="GridPane" xmlns:fx="http://javafx.com/fxml/1">
......
</fx:root>

LoginPaneFx 代码

public class LoginPaneFx extends GridPane {
  @FXML
  private TextField nameTxt;

  public LoginPaneFx() {
    try {
      FXMLLoader loader = new FXMLLoader(getClass().getResource("LoginPaneFx.fxml"));
      loader.setRoot(this);
      loader.setController(this);
      loader.load();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}

优点:
LoginPaneFx是一个JavaFX的独立控件,可以复用。

缺点:
如果程序中有很多JavaFX控件需要集成,每次都要手动构造FXCanvas,产生冗余代码。

2. 侵入式封装FXCanvas

注意:

FXML文件的根节点,不能使用<fx:root/>格式,因为Controller要继承SWT的Composite。Load FXML时,不可再调用setRoot()方法。

<GridPane xmlns:fx="http://javafx.com/fxml/1">
......
</GridPane>

CompositeFx 封装抽象类

public abstract class CompositeFx extends Composite {
  public CompositeFx(Composite parent, int style) {
    super(parent, style);
    this.setLayout(new FillLayout());

    try {
      FXCanvas fxCanvas = new FXCanvas(this, SWT.NONE);
      FXMLLoader loader = new FXMLLoader(getFxmlURL());
      loader.setController(this);
      fxCanvas.setScene(new Scene(loader.load()));
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Get the URL of a FXML file.
   *
   * @return a FXML's URL.
   */
  protected abstract URL getFxmlURL();
}

LoginComposite 代码

public class LoginComposite extends CompositeFx {
  @FXML
  private TextField nameTxt;

  public LoginComposite(Composite parent, int style) {
    super(parent, style);
    // Other logic
  }

  @Override
  protected URL getFxmlURL() {
    return getClass().getResource("LoginPaneFx.fxml");
  }
}

此处LoginComposite是一个SWT的Composite,只需要复写getFxmlURL()方法,使用时几乎不知道JavaFX的存在。

优点:

隐藏FXCanvas和FXMLLoader等相关代码,在大量需要嵌入JavaFX控件时,减少了冗余代码。

缺点:

Controller继承自SWT的Composite,硬性绑定,只能使用在SWT程序中,不能被其它JavaFX程序复用。