javafx 和swing
我很快将不得不在基于Swing的胖客户端中处理JavaFX –哦,对不起,我的意思是“多层富客户端”!
因此,这使我来看看JFXPanel 。 JFXPanel是一个javax.swing.JComponent,用于将JavaFX内容嵌入到Swing-UI中。 JFXPanel的用法类似于JPanel,并且可以通过EDT作为通用Swing组件进行访问,除了必须通过JavaFX应用程序线程来处理JavaFX组件之外。
为了解决这些问题,我创建了两个类似的面板(Swing + JavaFX),每个面板都有一个按钮,一个TextField和一个Label,并将它们放置在JSplitPane和JFrame中:
仔细看里面
要尝试Swing <-> JavaFX互操作性,按钮操作是将文本从TextField设置为JLabel,反之亦然。
JPanel处理通用的Swing东西没有什么特别的,但是JFXPanel包含JavaFX控件:
public class SwingFXPanel extends JFXPanel {private Button testButton;private TextField testTextField;private Label testLabel;private VBox pane;public SwingFXPanel() {init();}private void init() {testButton = new Button("I am a JavaFX Button");testTextField = new TextField();testLabel = new Label("empty");pane = new VBox();pane.setAlignment(Pos.CENTER);pane.getChildren().addAll(testTextField, testButton, testLabel);Platform.runLater(this::createScene);}private void createScene() {Scene scene = new Scene(pane);setScene(scene);}public Button getTestButton() {return testButton;}public TextField getTestTextField() {return testTextField;}public Label getTestLabel() {return testLabel;}
}
这里很重要:将场景添加到JavaFX Application线程内的JFXPanel:
Platform.runLater(this::createScene);
如果您致电:
createScene()
从另一个线程,您会获得Runtime-Exception:
java.lang.IllegalStateException: Not on FX application thread; currentThread = AWT-EventQueue-0
同样,每次与JavaFX相关内容的交互都必须放在JavaFX Application Thread上:
例如:
Platform.runLater(() -> {swingFXPanel.getTestLabel().setText(swingPanel.getTestTextField().getText());
});
public class InteropFrame extends JFrame {private JSplitPane centralSplitPane;private SwingPanel swingPanel;private SwingFXPanel swingFXPanel;public InteropFrame(){init();}private void init() {setTitle("Swing <-> JavaFX Interoperatbiliy");setSize(500, 500);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLayout(new BorderLayout());centralSplitPane = new JSplitPane();centralSplitPane.setDividerLocation(0.5);centralSplitPane.setResizeWeight(0.3);swingPanel = new SwingPanel();swingFXPanel = new SwingFXPanel();swingPanel.getTestButton().addActionListener((ActionEvent e) -> {Platform.runLater(() -> {swingFXPanel.getTestLabel().setText(swingPanel.getTestTextField().getText());});});swingFXPanel.getTestButton().setOnAction((javafx.event.ActionEvent t) -> {swingPanel.getTestLabel().setText(swingFXPanel.getTestTextField().getText());});centralSplitPane.setLeftComponent(swingPanel);centralSplitPane.setRightComponent(swingFXPanel);add(centralSplitPane, BorderLayout.CENTER);}
}
另外,处理FXML也很简单:
public class SwingFXMLPanel extends JFXPanel {@FXMLprivate Button testButton;@FXMLprivate TextField testTextField;@FXMLprivate Label testLabel;private VBox rootPane;private URL fxmlResource;public SwingFXMLPanel(URL fxmlResource){this.fxmlResource = fxmlResource;init();}private void init(){rootPane = new VBox();FXMLLoader loader = new FXMLLoader(fxmlResource);loader.setController(this);loader.setRoot(rootPane);try {loader.load();} catch (IOException ex) {Logger.getLogger(SwingFXMLPanel.class.getName()).log(Level.SEVERE, null, ex);}testButton.setText("I am a JavaFX Button");testLabel.setText("empty");Platform.runLater(this::createScene);}private void createScene() {Scene scene = new Scene(rootPane);setScene(scene);}public Button getTestButton() {return testButton;}public TextField getTestTextField() {return testTextField;}public Label getTestLabel() {return testLabel;}}
对我来说,让我的同事尽可能多地接受在Swing中使用JavaFX至关重要。
因此,我想简化特定的FX应用程序线程处理。 因此,如果使用JPanel的主要区别只是添加以下内容,那么也许可以实现:
private void createScene() {Scene scene = new Scene(rootPane);setScene(scene);}
并致电:
Platform.runLater(this::createScene);
在JFXPanel中 。
- 您可以在此处找到完整的示例代码。
翻译自: https://www.javacodegeeks.com/2014/11/swing-and-javafx-working-with-jfxpanel.html
javafx 和swing