1 /* 2 * Copyright (c) 2008, 2018, Oracle and/or its affiliates. 3 * All rights reserved. Use is subject to license terms. 4 * 5 * This file is available and licensed under the following license: 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the distribution. 16 * - Neither the name of Oracle Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package ensemble.samples.language.swing; 34 35 import java.awt.BorderLayout; 36 import java.awt.Color; 37 import java.awt.Component; 38 import java.awt.Dimension; 39 import java.text.DecimalFormat; 40 import javafx.application.Platform; 41 import javafx.beans.value.ChangeListener; 42 import javafx.beans.value.ObservableValue; 43 import javafx.collections.FXCollections; 44 import javafx.collections.ObservableList; 45 import javafx.embed.swing.JFXPanel; 46 import javafx.event.ActionEvent; 47 import javafx.event.EventHandler; 48 import javafx.geometry.HPos; 49 import javafx.geometry.Insets; 50 import javafx.geometry.VPos; 51 import javafx.scene.Scene; 52 import javafx.scene.chart.BarChart; 53 import javafx.scene.chart.CategoryAxis; 54 import javafx.scene.chart.Chart; 55 import javafx.scene.chart.NumberAxis; 56 import javafx.scene.chart.XYChart; 57 import javafx.scene.control.Button; 58 import javafx.scene.control.Label; 59 import javafx.scene.control.TextField; 60 import javafx.scene.layout.ColumnConstraints; 61 import javafx.scene.layout.GridPane; 62 import javafx.scene.layout.Pane; 63 import javafx.scene.layout.Priority; 64 import javafx.scene.web.WebEngine; 65 import javafx.scene.web.WebView; 66 67 import javax.swing.JFrame; 68 import javax.swing.JLabel; 69 import javax.swing.JPanel; 70 import javax.swing.JScrollPane; 71 import javax.swing.JSplitPane; 72 import javax.swing.JTable; 73 import javax.swing.JTabbedPane; 74 import javax.swing.SwingUtilities; 75 import javax.swing.UIManager; 76 import javax.swing.event.TableModelEvent; 77 import javax.swing.event.TableModelListener; 78 import javax.swing.table.DefaultTableCellRenderer; 79 80 /** 81 * SwingInterop 82 * 83 * Note using the browser might require setting the properties 84 * - http.proxyHost 85 * - http.proxyPort 86 * 87 * e.g. -Dhttp.proxyHost=webcache.mydomain.com -Dhttp.proxyPort=8080 88 * 89 */ 90 public class SwingInterop extends JPanel { 91 92 private static final int PANEL_WIDTH = 675; 93 private static final int PANEL_HEIGHT = 400; 94 private static final int TABLE_PANEL_HEIGHT = 100; 95 private static JFXPanel chartFxPanel; 96 private static JFXPanel browserFxPanel; 97 private static SampleTableModel tableModel; 98 private Chart chart; 99 private Pane browser; 100 101 void initUI() { 102 tableModel = new SampleTableModel(); 103 // create javafx panel for charts 104 chartFxPanel = new JFXPanel(); 105 chartFxPanel.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); 106 107 // create javafx panel for browser 108 browserFxPanel = new JFXPanel(); 109 110 //create tabbed pane 111 JTabbedPane tabbedPane = new JTabbedPane(); 112 113 //JTable 114 JTable table = new JTable(tableModel); 115 table.setAutoCreateRowSorter(true); 116 table.setGridColor(Color.DARK_GRAY); 117 DecimalFormatRenderer renderer = new DecimalFormatRenderer(); 118 renderer.setHorizontalAlignment(JLabel.RIGHT); 119 for (int i = 0; i < table.getColumnCount(); i++) { 120 table.getColumnModel().getColumn(i).setCellRenderer(renderer); 121 } 122 JScrollPane tablePanel = new JScrollPane(table); 123 tablePanel.setPreferredSize(new Dimension(PANEL_WIDTH, 124 TABLE_PANEL_HEIGHT)); 125 126 JPanel chartTablePanel = new JPanel(); 127 chartTablePanel.setLayout(new BorderLayout()); 128 129 //Split pane that holds both chart and table 130 JSplitPane jsplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 131 jsplitPane.setTopComponent(chartTablePanel); 132 jsplitPane.setBottomComponent(tablePanel); 133 jsplitPane.setDividerLocation(410); 134 chartTablePanel.add(chartFxPanel, BorderLayout.CENTER); 135 136 tabbedPane.addTab("JavaFX Chart and Swing JTable", jsplitPane); 137 tabbedPane.addTab("Web Browser", browserFxPanel); 138 139 add(tabbedPane, BorderLayout.CENTER); 140 141 // create JavaFX scene 142 Platform.runLater(new Runnable() { 143 public void run() { 144 createScene(); 145 } 146 }); 147 } 148 149 public static void main(String[] args) { 150 SwingUtilities.invokeLater(new Runnable() { 151 152 @Override 153 public void run() { 154 try { 155 final String ui = 156 "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"; 157 UIManager.setLookAndFeel(ui); 158 } catch (Exception e) {} 159 160 JFrame frame = new JFrame("JavaFX in Swing"); 161 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 162 163 SwingInterop app = new SwingInterop(); 164 app.initUI(); 165 166 frame.setContentPane(app); 167 168 frame.pack(); 169 frame.setLocationRelativeTo(null); 170 frame.setVisible(true); 171 } 172 }); 173 } 174 175 private void createScene() { 176 chart = createBarChart(); 177 chartFxPanel.setScene(new Scene(chart)); 178 browser = createBrowser(); 179 browserFxPanel.setScene(new Scene(browser)); 180 } 181 182 private BarChart createBarChart() { 183 CategoryAxis xAxis = new CategoryAxis(); 184 ObservableList<String> xCategories = 185 FXCollections.observableArrayList(tableModel.getColumnNames()); 186 xAxis.setCategories(xCategories); 187 xAxis.setLabel("Year"); 188 189 double tickUnit = tableModel.getTickUnit(); 190 191 NumberAxis yAxis = new NumberAxis(); 192 yAxis.setTickUnit(tickUnit); 193 yAxis.setLabel("Units Sold"); 194 195 final BarChart bChart = new BarChart(xAxis, yAxis, 196 tableModel.getBarChartData()); 197 final TableModelListener tableListener = (TableModelEvent e) -> { 198 if (e.getType() == TableModelEvent.UPDATE) { 199 final int row = e.getFirstRow(); 200 final int column = e.getColumn(); 201 final Object value = 202 ((SampleTableModel) e.getSource()).getValueAt(row, 203 column); 204 Platform.runLater(new Runnable() { 205 @Override 206 public void run() { 207 XYChart.Series<String, Number> s = 208 (XYChart.Series<String, Number>) 209 bChart.getData().get(row); 210 BarChart.Data data = s.getData().get(column); 211 data.setYValue(value); 212 } 213 }); 214 } 215 }; 216 tableModel.addTableModelListener(tableListener); 217 return bChart; 218 } 219 220 private Pane createBrowser() { 221 Double widthDouble = new Integer(PANEL_WIDTH).doubleValue(); 222 Double heightDouble = new Integer(PANEL_HEIGHT).doubleValue(); 223 WebView view = new WebView(); 224 view.setMinSize(widthDouble, heightDouble); 225 view.setPrefSize(widthDouble, heightDouble); 226 final WebEngine eng = view.getEngine(); 227 final String message = "Do you need to specify web proxy information?"; 228 final Label warningLabel = new Label(message); 229 eng.load("http://www.oracle.com/us/index.html"); 230 231 final ChangeListener<Number> handler = 232 (ObservableValue<? extends Number> observable, 233 Number oldValue, Number newValue) -> { 234 if (warningLabel.isVisible()) { 235 warningLabel.setVisible(false); 236 } 237 }; 238 eng.getLoadWorker().progressProperty().addListener(handler); 239 240 final String url = "http://www.oracle.com/us/index.html"; 241 final TextField locationField = new TextField(url); 242 locationField.setMaxHeight(Double.MAX_VALUE); 243 Button goButton = new Button("Go"); 244 goButton.setMinWidth(Button.USE_PREF_SIZE); 245 goButton.setDefaultButton(true); 246 EventHandler<ActionEvent> goAction = (ActionEvent event) -> { 247 eng.load(locationField.getText().startsWith("http://") ? 248 locationField.getText() : 249 "http://" + locationField.getText()); 250 }; 251 goButton.setOnAction(goAction); 252 locationField.setOnAction(goAction); 253 final ChangeListener<String> webListener = 254 (ObservableValue<? extends String> observable, 255 String oldValue, String newValue) -> { 256 locationField.setText(newValue); 257 }; 258 eng.locationProperty().addListener(webListener); 259 GridPane grid = new GridPane(); 260 grid.setPadding(new Insets(5)); 261 grid.setVgap(5); 262 grid.setHgap(5); 263 GridPane.setConstraints(locationField, 0, 0, 1, 1, 264 HPos.CENTER, VPos.CENTER, 265 Priority.ALWAYS, Priority.SOMETIMES); 266 GridPane.setConstraints(goButton, 1, 0); 267 GridPane.setConstraints(view, 0, 1, 2, 1, 268 HPos.CENTER, VPos.CENTER, 269 Priority.ALWAYS, Priority.ALWAYS); 270 GridPane.setConstraints(warningLabel, 0, 2, 2, 1, 271 HPos.CENTER, VPos.CENTER, 272 Priority.ALWAYS, Priority.SOMETIMES); 273 grid.getColumnConstraints().addAll( 274 new ColumnConstraints(widthDouble - 200, widthDouble - 200, 275 Double.MAX_VALUE, Priority.ALWAYS, 276 HPos.CENTER, true), 277 new ColumnConstraints(40, 40, 40, 278 Priority.NEVER, HPos.CENTER, true)); 279 grid.getChildren().addAll(locationField, goButton, warningLabel, view); 280 return grid; 281 } 282 283 private static class DecimalFormatRenderer extends DefaultTableCellRenderer { 284 private static final DecimalFormat formatter = new DecimalFormat("#.0"); 285 286 @Override 287 public Component getTableCellRendererComponent(JTable table, Object value, 288 boolean isSelected, 289 boolean hasFocus, 290 int row, int column) { 291 value = formatter.format((Number) value); 292 return super.getTableCellRendererComponent(table, value, isSelected, 293 hasFocus, row, column); 294 } 295 } 296 }