登录面板是JavaFX,运行在SWT Shell里面。
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程序复用。