在Swing和Swt中使用JavaFX

时间:2023-01-28 11:19:35

本人从08年12月份,JavaFX发布第一个版本开始关注它的发展。


 算算到现在,也差不多是第五个年头了。期间经历了一些动荡,但JavaFX还是坚持着发展了下来,也经历了很多改变(这也是Java技术的特点,不会像微软对技术的抛弃和更新换代很频繁),由以前顺应富互联网技术发展的单纯的JavaFX脚本语言,到现在已经变为完全用于取代Swing的技术。

  

 虽然是为了取代Swing,但任何的技术为了不造成很大的影响,都必须有一个逐步换代的过程。如果单纯的从JDK中剔除Swing而增加JavaFX的话,将会造成世界数不清的程序无法运行,影响不可估量(就像JDK中有很多以前不合理的旧的类库,就算有新的可替代的方案,也不能将以前的完全删除,所以JDK其实越来越臃肿)。这里,我们将会介绍一下如何在Swing中使用JavaFX。


  首先我们要明白,不管是Swing还是JavaFX,GUI的构建必须要各自的EDT(事件分发线程)中进行,这也是在其他线程中操作UI会出现error的原因。


  而在JavaFX中,新增加了JFXPanel。这个组件是JavaFX和Swing进行混合编程的桥梁。

  下面我们来看看JFXPanel的继承关系。

  在Swing和Swt中使用JavaFX

  


  大家可以看到,JFXPanel是继承于JComponent的。而JavaFX的UI控件都是继承于javafx.scene.control.Control。所以很明显,它其实是一个Swing组件,而非JavaFX的组件。


  下面我们来看看JPanel的继承关系。

  在Swing和Swt中使用JavaFX


  继承关系基本相同,也就是说,凡是在使用JPanel的地方,我们都可以用JFXPanel来替代。JFXPanel中有一个setScene方法,可以设置其中显示的JavaFX内容。


  根据文档介绍,setScene方法可以在Swing和JavaFX的EDT中使用。也可以说,setScene才是将JavaFX和Swing结合起来的关键。


  不过由于JavaFX的GUI的构建也需要在JavaFX的事件分发线程中进行。所以我们还需要用到另外一个类Platform。

  Platform.runLater(new Runnable())中间执行的是JavaFX的事件分发线程。我们可以在Runnable中进行JavaFX的UI的创建。


  下面我们来看一个简单的示例-----在Swing中嵌入一个JavaFX的网页浏览器。


  

[java] view plaincopy
  1. import java.awt.BorderLayout;  
  2. import java.awt.Toolkit;  
  3.   
  4. import javafx.application.Platform;  
  5. import javafx.embed.swing.JFXPanel;  
  6. import javafx.event.ActionEvent;  
  7. import javafx.event.EventHandler;  
  8. import javafx.scene.Group;  
  9. import javafx.scene.Scene;  
  10. import javafx.scene.control.Button;  
  11. import javafx.scene.control.TextField;  
  12. import javafx.scene.layout.HBox;  
  13. import javafx.scene.layout.VBox;  
  14. import javafx.scene.web.WebEngine;  
  15. import javafx.scene.web.WebView;  
  16.   
  17. import javax.swing.JFrame;  
  18.   
  19. public class MainClass {  
  20.     private static final int WIDTH = 800;  
  21.     private static final int HEIGHT = 600;  
  22.     private static final String url = "http://blog.csdn.net/ml3947";  
  23.     private static final String urlStart = "http://";  
  24.   
  25.     /** 
  26.      * @param args 
  27.      */  
  28.     public static void main(String[] args) {  
  29.         JFrame frame = new JFrame("JavaFX in Swing");  
  30.         final JFXPanel webBrowser = new JFXPanel();  
  31.         frame.setLayout(new BorderLayout());  
  32.         frame.add(webBrowser, BorderLayout.CENTER);  
  33.         Platform.runLater(new Runnable() {  
  34.   
  35.             @Override  
  36.             public void run() {  
  37.                 Group root = new Group();  
  38.                 Scene scene = new Scene(root, WIDTH, HEIGHT);  
  39.                 webBrowser.setScene(scene);  
  40.                 Double widthDouble = new Integer(WIDTH).doubleValue();  
  41.                 Double heightDouble = new Integer(HEIGHT).doubleValue();  
  42.   
  43.                 VBox box = new VBox(10);  
  44.                 HBox urlBox = new HBox(10);  
  45.                 final TextField urlTextField = new TextField();  
  46.                 urlTextField.setText(url);  
  47.                 Button go = new Button("go");  
  48.                 urlTextField.setPrefWidth(WIDTH - 70);  
  49.                 urlBox.getChildren().addAll(urlTextField, go);  
  50.   
  51.                 WebView view = new WebView();  
  52.                 view.setMinSize(widthDouble, heightDouble);  
  53.                 view.setPrefSize(widthDouble, heightDouble);  
  54.                 final WebEngine eng = view.getEngine();  
  55.                 eng.load(url);  
  56.                 root.getChildren().add(view);  
  57.   
  58.                 box.getChildren().add(urlBox);  
  59.                 box.getChildren().add(view);  
  60.                 root.getChildren().add(box);  
  61.   
  62.                 go.setOnAction(new EventHandler<ActionEvent>() {  
  63.                     @Override  
  64.                     public void handle(ActionEvent event) {  
  65.                         if (!urlTextField.getText().startsWith(urlStart)) {  
  66.                             eng.load(urlStart + urlTextField.getText());  
  67.                         } else {  
  68.                             eng.load(urlTextField.getText());  
  69.                         }  
  70.                     }  
  71.                 });  
  72.             }  
  73.         });  
  74.   
  75.         int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;  
  76.         int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;  
  77.   
  78.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  79.         frame.setSize(WIDTH, HEIGHT);  
  80.         frame.setLocation((screenWidth - WIDTH) / 2, (screenHeight - HEIGHT) / 2);  
  81.         frame.setVisible(true);  
  82.     }  
  83.   
  84. }  

  这是一个很简单的例子。

  我们创建了JFrame和JFXPanel,然后在Platform.runLater中进行Scene的创建,并设置到JFXPanel中。

  我们创建了一个Textfield用来输入网址,创建了一个JavaFX Button来跳转到网址。判断网址是不是http://开头并做简单的处理。


  下面看看运行效果:

  在Swing和Swt中使用JavaFX

  

  如图所示。



   另外,在Swt中使用的话是JFXCanvas,由于实现机制的问题,我们并不需要像在Swing中使用Platform类。而JFXCanvas也是org.eclipse.swt.widgets.Canvas的直接子类,我们可以直接使用。

  示例如下:

  

[java] view plaincopy
  1. public class JFXInSwt {  
  2.     private static Scene createScene() {  
  3.         Group group = new Group();  
  4.         Scene scene = new Scene(group);  
  5.         Button button = new Button("JFX Button");  
  6.         group.getChildren().add(button);  
  7.         return scene;  
  8.     }  
  9.   
  10.     public static void main(String[] args) {  
  11.         Display display = new Display();  
  12.         Shell shell = new Shell(display);  
  13.         shell.setLayout(new FillLayout());  
  14.         FXCanvas canvas = new FXCanvas(shell, SWT.NONE);  
  15.         Scene scene = createScene();  
  16.         canvas.setScene(scene);  
  17.         shell.open();  
  18.         while (!shell.isDisposed()) {  
  19.             if (!display.readAndDispatch()) display.sleep();  
  20.         }  
  21.         display.dispose();  
  22.     }  
  23. }  


---------------------------------------------------------------------------------------

  很不幸,由于Sourceforge的项目首页貌似被屏蔽了,就算我绑定了自己的一个一级域名...也是有时可以访问有时不能访问,所以示例不准备放在上面了。过一段时间买个空间自己建个站。