JavaFX Script被抛弃以后,很久不关心JavaFX了,偶然发现JavaFX已经发展到2.2,而且已经绑定到JDK7中,看来Oracle对它还是蛮重视的。
看到有人在论坛提问TWaver有没有JavaFX版本,于是去Oracle网站上逛了一下,发现可以将JavaFX集成进Swing程序中,真是福音啊,立马动手写了个Demo,集成起来还是很方便的。
运行效果
代码分析
窗体中间是个很典型的Network,上下各是一个JavaFX容器,上面容器中包含一个Slider,滑动时可以改变TWaver选中Node的RenderColor,下面的容器中包含一些Text,选中Network中的Node并拖动的时候在Text组件上显示Node的name和location。
在这个Demo里,程序架构还是Swing,JavaFX提供了一个名为JFXPanel的组件可以嵌入到Swing容器中,JFXPanel内可以放JavaFX的组件,需要注意,Swing和JavaFX的线程不同,官方的原文是:"JavaFX data should be accessed only on the JavaFX User thread","Swing data should be changed only on the EDT",所以如果要在Swing中修改JavaFX的数据,应该使用Platform#runLater包装,本例中,拖动Node时修改JavaFX的Text组件的相关代码:
network.getDataBox().addElementPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if("location".equals(evt.getPropertyName())){ Element element= (Element) evt.getSource(); final String name=element.getName(); final double x=element.getX(); final double y=element.getY(); Platform.runLater(new Runnable() { @Override public void run() { nameText.setText(name); locationText.setText("X:"+x+" Y:"+y); } }); } } });
同样,如果要在JavaFX中修改Swing数据,也要用SwingUtilities#invokeLater包装,本例中,滑动Slider修改选中Node的Render Color代码如下:
slider.valueProperty().addListener(new ChangeListener<Number>() { public void changed(ObservableValue<? extends Number> ov, Number old_val,final Number new_val) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Iterator it=network.getSelectionModel().selection(); while (it.hasNext()){ Element element= (Element) it.next(); element.putRenderColor(new java.awt.Color(new_val.intValue())); } } }); } });
最后附上全部代码:
public class Test1 { static TNetwork network; static Text nameText; static Text locationText; static Slider slider; private static void initAndShowGUI() { initNetwork(); JFrame frame = new JFrame("TWaver With JavaFX"); frame.getContentPane().setLayout(new BorderLayout()); frame.setSize(500, 300); frame.setVisible(true); frame.getContentPane().add(network); final JFXPanel controlFXPanel = new JFXPanel(); frame.add(controlFXPanel,BorderLayout.NORTH); final JFXPanel statusFXPanel = new JFXPanel(); frame.add(statusFXPanel,BorderLayout.SOUTH); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); network.getDataBox().addElementPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if("location".equals(evt.getPropertyName())){ Element element= (Element) evt.getSource(); final String name=element.getName(); final double x=element.getX(); final double y=element.getY(); Platform.runLater(new Runnable() { @Override public void run() { nameText.setText(name); locationText.setText("X:"+x+" Y:"+y); } }); } } }); Platform.runLater(new Runnable() { @Override public void run() { initFX(statusFXPanel,controlFXPanel); } }); } private static void initNetwork(){ network=new TNetwork(); twaver.Node node1=new Node(); node1.setName("node1"); twaver.Node node2=new Node(); node2.setLocation(200,100); node2.setName("node2"); Link link=new Link(node1,node2); network.getDataBox().addElement(node1); network.getDataBox().addElement(node2); network.getDataBox().addElement(link); } private static void initFX(JFXPanel statusFXPanel,JFXPanel controlFXPanel) { Scene scene = createStatusScene(); statusFXPanel.setScene(scene); statusFXPanel.validate(); Scene controlScene=createControlScene(); controlFXPanel.setScene(controlScene); controlFXPanel.validate(); } private static Scene createControlScene(){ Group root = new Group(); Scene scene = new Scene(root, Color.ALICEBLUE); HBox hbox=new HBox(); slider =new Slider(0,16777215,0); slider.setPrefHeight(30); slider.setPrefWidth(300); slider.valueProperty().addListener(new ChangeListener<Number>() { public void changed(ObservableValue<? extends Number> ov, Number old_val, final Number new_val) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Iterator it = network.getSelectionModel().selection(); while (it.hasNext()) { Element element = (Element) it.next(); element.putRenderColor(new java.awt.Color(new_val.intValue())); } } }); } }); Label label=new Label("颜色:"); label.setPrefHeight(30); hbox.getChildren().add(label); hbox.getChildren().add(slider); root.getChildren().add(hbox); return scene; } private static Scene createStatusScene() { Group root = new Group(); Scene scene = new Scene(root, Color.ALICEBLUE); VBox vbox=new VBox(); vbox.setPrefWidth(300); vbox.setPrefHeight(20); HBox hbox=new HBox(); nameText=new Text(); hbox.getChildren().add(new Label(" Name:")); hbox.getChildren().add(nameText); hbox.getChildren().add(new Text(" ")); locationText=new Text(); hbox.getChildren().add(new Label("Location:")); hbox.getChildren().add(locationText); vbox.getChildren().add(hbox); root.getChildren().add(vbox); return (scene); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { initAndShowGUI(); } }); } }