Swap between JavaFX & Swing control - java

I am working on a swing application using JavaFX controls.
in this application i have three controls buttons WebView and JTable.
on clicking on button1 table should be added on the screen and web view should be removed while on clicking on other button
table should be removed and web view should be added.
I am using the following code.
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.web.*;
import javafx.stage.Stage;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
public class webviewtestclass extends JFrame implements ActionListener {
JFXPanel fxpanel,fxpanel1;
static String filepath;
JTable table;
public webviewtestclass()
{
setLayout(null);
JButton b1= new JButton("OK");
JButton b2= new JButton("OKK");
add(b1);
add(b2);
b1.setBounds(20,50,50,30);
b2.setBounds(70,50,50,30);
b1.addActionListener(this);
b2.addActionListener(this);
fxpanel= new JFXPanel();
add(fxpanel);
fxpanel.setBounds(10,50,1000,800);
Object obj=new Object[50][20];
String title[]={"head1","head2"};
table=new JTable(title,obj);
add(table);
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getActionCommand().equals("OK"))
{
remove(fxpanel);
add(table);
}
if(ae.getActionCommand().equals("OKK"))
{
remove(table);
add(fxpanel);
}
Platform.runLater(new Runnable() {
public void run()
{
initFx(fxpanel);
}}
);
}
private static void initFx(final JFXPanel fxpanel)
{
String htmlpath="d:/lcrux/html/";
Group group= new Group();
Scene scene= new Scene(group);
fxpanel.setScene(scene);
WebView webview = new WebView ();
group.getChildren().add(webview);
webview.setMinSize(1200,800);
webview.setMaxSize(1200,800);
webview.setVisible(true);
final WebEngine eng = webview.getEngine();
File htmlFile = new File(htmlpath+filepath);
try
{
eng.load(htmlFile.toURI().toURL().toString());
}
catch(Exception ex)
{
}
}
public static void main(final String args[])
{
webviewtestclass frm=new webviewtestclass();
frm.show();
}
}

Put both components in a CardLayout to swap between them. Code using a CardLayout can be seen in this answer.

Related

Embedded browser in Netbeans using javaFX WebView in Swing application

I am trying to implement embedded browser in my java Netbeans project so far so good but still the browser is not sophisticated enough to store cookies or any advanced features my goal is basically to be able to access google account and check email or calendar or any similar operation.. can someone please direct me to the right code? thanks in advance.
here is my code:
import com.sun.javafx.application.PlatformImpl;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
/**
* SwingFXWebView
*/
public class SwingFXWebView extends JPanel {
private Stage stage;
private WebView browser;
private JFXPanel jfxPanel;
private JButton swingButton;
private WebEngine webEngine;
public SwingFXWebView(){
initComponents();
}
public static void main(String ...args){
// Run this later:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JFrame frame = new JFrame();
frame.getContentPane().add(new SwingFXWebView());
frame.setMinimumSize(new Dimension(640, 480));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
private void initComponents(){
jfxPanel = new JFXPanel();
createScene();
setLayout(new BorderLayout());
add(jfxPanel, BorderLayout.CENTER);
swingButton = new JButton();
swingButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(new Runnable() {
#Override
public void run() {
webEngine.reload();
}
});
}
});
swingButton.setText("Reload");
add(swingButton, BorderLayout.SOUTH);
}
/**
* createScene
*
* Note: Key is that Scene needs to be created and run on "FX user thread"
* NOT on the AWT-EventQueue Thread
*
*/
private void createScene() {
PlatformImpl.startup(new Runnable() {
#Override
public void run() {
stage = new Stage();
stage.setTitle("Hello Java FX");
stage.setResizable(true);
Group root = new Group();
Scene scene = new Scene(root,80,20);
stage.setScene(scene);
// Set up the embedded browser:
browser = new WebView();
webEngine = browser.getEngine();
webEngine.load("https://www.google.com");
//https://calendar.google.com
ObservableList<Node> children = root.getChildren();
children.add(browser);
jfxPanel.setScene(scene);
}
});
}
}

JavaFX Pane inside of a Tab

I want to extend a Class from Pane and then use the setContent() method from a tab from TabPane to display the Pane inside this Tab. It worked in Swing when I extended from JPanel but if I try something similar in JavaFX it only displays the tab itself and stays empty below.
I want to handle the content of the tabs in separate classes, am I doing something completely wrong here?
Swing version:
import java.awt.*;
import javax.swing.*;
import java.util.*;
public class Home extends JFrame{
private JTabbedPane jTabbedPane1 = new JTabbedPane();
private Example ex = new Example();
public static void main(String[] args) {
Home h1 = new Home();
h1.ex= new Example();
h1.jTabbedPane1.add("test",h1.ex);
} // end of main
public Home() {
// Frame-Initialisierung
super();
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setSize(200,200);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
// Anfang Komponenten
jTabbedPane1.setBounds(0, 0, 100, 100);
cp.add(jTabbedPane1);
setVisible(true);
} // end of public home
} // end of class Home
import java.awt.*;
import javax.swing.*;
import java.util.*;
public class Example extends JPanel {
private JList jList1 = new JList();
private DefaultListModel jList1Model = new DefaultListModel();
private JScrollPane jList1ScrollPane = new JScrollPane(jList1);
public Example(){
super();
setLayout(null);
jList1.setModel(jList1Model);
jList1ScrollPane.setBounds(0, 0, 100, 100);
add(jList1ScrollPane);
}
} // end of class Example
Not working in JavaFX version:
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Home extends Application {
private TabPane tabpane = new TabPane();
private Example ex;
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("TEST");
Pane layout = new Pane();
tabpane.setLayoutX(-8);
tabpane.setLayoutY(24);
tabpane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
Tab tab = new Tab();
tab.setText("new tab");
tab.setContent(new Rectangle(200,200));
this.ex = new Example();
tab.setContent(ex);
tabpane.getTabs().add(tab);
layout.getChildren().add(tabpane);
Scene scene = new Scene(layout, 500, 500);
scene.getStylesheets().clear();
scene.getStylesheets().add(Home.class.getResource("style.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
import java.util.ArrayList;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ListView;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Example extends Pane{
ListView<String> list = new ListView<String>();
public void start(Stage primaryStage) {
ArrayList<String> arraytest = new ArrayList<String>();
arraytest.add("test1");
arraytest.add("test2");
ObservableList<String> test = FXCollections.observableArrayList(arraytest);
list.setItems(test);
list.setLayoutX(10);
list.setLayoutY(10);
list.setPrefWidth(270);
list.setPrefHeight(270);
getChildren().add(list);
}
}
Your Swing example is incorrectly synchronized and suffers from an inflexible layout having absolute positioning. The example should be discarded except to observe that Pane "may be used directly in cases where absolute positioning of children is required." In this case, your JavaFX example does not.
In the JavaFX variation below, Example constructs the desired ListView and makes it available via the getContent() method. Home then uses that content for the tab. Resize the enclosing stage to see the effect.
tab.setContent(example.getContent());
As an aside, the private static class Example is semantically equivalent to a class having package-private access, making it easy to test in situ and later refactor into a separate class.
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.stage.Stage;
/** #see https://stackoverflow.com/a/44102580/230513 */
public class Home extends Application {
private TabPane tabpane = new TabPane();
private Example example = new Example();
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Test");
tabpane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
Tab tab = new Tab();
tab.setText("Tab One");
tab.setContent(example.getContent());
tabpane.getTabs().add(tab);
Scene scene = new Scene(tabpane);
primaryStage.setScene(scene);
primaryStage.show();
}
private static class Example {
ListView<String> view = new ListView<>();
public Example() {
ObservableList<String> list = FXCollections.observableArrayList(
"Test 1", "Test 2", "Test 3");
view.setItems(list);
}
public ListView getContent() {
return view;
}
}
public static void main(String[] args) {
launch(args);
}
}

JAVAFX Objects don't free Heap Memory

I have a simple JavaFX Application that open a Browser and shows google page. After exit the Application and free all objects, I can see that the JavaFX objects like Scene, Stage, WebView and WebEngine are alive in the heap memory after call GC.
I can see this objects with JProfiler and other Profiler tools.
This is my Test code:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.stage.Stage;
import javax.swing.JButton;
import javax.swing.JFrame;
public class TestMemoryLeak
{
private Stage anotherStage;
private Application app;
public void initFrame()
{
JButton btnStart = new JButton("Start");
ActionListener a1 = new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread javaFxThread = new Thread(new Runnable() {
#Override
public void run() {
new JFXPanel();
Platform.runLater(new Runnable() {
#Override
public void run() {
try
{
app = MyApplication.class.newInstance();
anotherStage = new Stage();
app.start(anotherStage);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
});
javaFxThread.setDaemon(true);
javaFxThread.start();
}
};
btnStart.addActionListener(a1);
JButton btnStop = new JButton("Stop");
ActionListener a2 = new ActionListener() {
public void actionPerformed(ActionEvent e) {
Platform.runLater(new Runnable() {
public void run() {
try
{
anotherStage.close();
anotherStage = null;
app.stop();
Platform.exit();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
};
btnStop.addActionListener(a2);
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(btnStart);
frame.getContentPane().add(btnStop);
frame.setTitle("Memory Leak");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
new TestMemoryLeak().initFrame();
}
}
And my JavaFX Application:
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class MyApplication extends Application {
private Scene scene;
#Override
public void start(Stage stage)
{
// create the scene
stage.setTitle("Web View");
scene = new Scene(new Browser(), 800, 600, Color.web("#666970"));
stage.setScene(scene);
stage.show();
}
}
class Browser extends Region {
WebView browser = new WebView();
WebEngine engine = browser.getEngine();
public Browser() {
// load the web page
engine.load("http://www.google.es");
//add the web view to the scene
getChildren().add(browser);
}
#Override
protected void layoutChildren() {
double w = getWidth();
double h = getHeight();
layoutInArea(browser,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
}
}
To test the application click on Start Button to show google web page, click on Stop Button to stop the application, run a Profiler tool, and call gc, the JavaFX classes are alive.
I am using java version "1.7.0_51" and windows 8.1
Is there something wrong in my code? Or this is the normal behavior?
Thanks for your responses.

Add textfields dynamically in JavaFX

So I have this code here, and it is supposed to dynamically add textfields and buttons depending on how many times the user presses New Column however it is not adding anything.
newColumn.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
String column = columns.getText();
columns.clear();
final HBox hbox1 = new HBox();
final TextField textField = new TextField();
textField.setText(column);
Button delete = new Button("X");
vbox.getChildren().add(hbox1);
delete.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
vbox.getChildren().remove(hbox1);
}
});
}
});
This is the part of the code that is supposed to add the new buttons. Here's the rest of the code, that displays the window and everythig else:
package GUI;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Example extends Application{
/**
* #param args
*/
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new Group());
primaryStage.setTitle("Parameters");
primaryStage.setWidth(500);
primaryStage.setHeight(800);
showWindow(scene);
primaryStage.setScene(scene);
primaryStage.show();
}
public void showWindow(Scene scene){
final VBox vbox = new VBox();
final HBox hbox = new HBox();
final TextField columns = new TextField();
Button newColumn = new Button("New Column");
Button done = new Button("Done");
hbox.setSpacing(5);
hbox.getChildren().addAll(columns, newColumn);
vbox.setSpacing(5);
vbox.setPadding(new Insets(20, 0, 0, 20));
vbox.getChildren().addAll(hbox);
newColumn.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
String column = columns.getText();
columns.clear();
final HBox hbox1 = new HBox();
final TextField textField = new TextField();
textField.setText(column);
Button delete = new Button("X");
vbox.getChildren().add(hbox1);
delete.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e){
vbox.getChildren().remove(hbox1);
}
});
}
});
vbox.getChildren().addAll(done);
((Group) scene.getRoot()).getChildren().addAll(vbox);
}
}
I'm also using JavaFX, if that helps.
If you want to be dynamic in adding and removing JComponents , consider storing them in an ArrayList or Vector. In the start, there will be a default JTextField and then then user will add one after another.
In the actionPerformed() of the JButton, create a new JTextField of whatever size you want. Call invalidate() on the content pane of your JFrame and then just add whatever component you need.
Good to go !
SSCCE
package stack;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class DynamicButtons extends JFrame{
JButton addMore = new JButton("AddMore");
Container contentPane = null;
public DynamicButtons(){
contentPane = this.getContentPane();
contentPane.setLayout(new FlowLayout());
addMore.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
JButton newButton = new JButton("ABCD");
contentPane.invalidate();
contentPane.add(newButton);
pack();
}
});
contentPane.add(addMore);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
new DynamicButtons();
}
});
}
}
The OP needs JavaFX
1. Get your whatever Pane you are using.
2. Call the yourPane.getChildren()
3. In the listener of the button, just add the child to the list you obtained above

How do I use javax.swing components in an application?

Disclaimer: I am very new to Java, but I've been building .NET applications for 13 years.
I'm trying to build this Java application that does some basic calculations for tutoring. It's honestly not that big of a program, but I can't even get it to the Hello, World! state! I have a requirement that's making it difficult:
GUI should be built using javax.swing components jButton, jLabel, jTextField, jTextArea, jFrame, and jPanel.
So, I downloaded NetBeans 7.3 and created a JavaFX in Swing application. The default code obviously works but it uses Button instead of JButton:
private void createScene() {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
fxContainer.setScene(new Scene(root));
}
so I when I change it to use a JButton I have to also change the type the root is built from. While banging my head against the wall I found an example here (not directly related) that used the JRootPane and I thought that might work in place of the StackPane. So I refactored the code like this:
private void createScene() {
JButton btn = new JButton();
btn.setText("Say 'Hello World'");
JRootPane root = new JRootPane();
root.getContentPane().add(btn);
fxContainer.setScene(new Scene(root));
}
and that code is fine except for fxContainer.setScene(new Scene(root)); because root isn't a Parent.
FYI, the application class implements JApplet and has a main and init that looks like this:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
}
JFrame frame = new JFrame("Tutoring Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet = new TutoringCalculator();
applet.init();
frame.setContentPane(applet.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
applet.start();
}
});
}
#Override
public void init() {
fxContainer = new JFXPanel();
fxContainer.setPreferredSize(new Dimension(JFXPANEL_WIDTH_INT, JFXPANEL_HEIGHT_INT));
add(fxContainer, BorderLayout.CENTER);
// create JavaFX scene
Platform.runLater(new Runnable() {
#Override
public void run() {
createScene();
}
});
}
How can I fulfill the requirement stated above? Am I really going about this whole thing the wrong way?
SSCCE
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tutoringcalculator;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
*
* #author Owner
*/
public class TutoringCalculator extends JApplet {
private static final int JFXPANEL_WIDTH_INT = 300;
private static final int JFXPANEL_HEIGHT_INT = 250;
private static JFXPanel fxContainer;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
}
JFrame frame = new JFrame("Tutoring Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet = new TutoringCalculator();
applet.init();
frame.setContentPane(applet.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
applet.start();
}
});
}
#Override
public void init() {
fxContainer = new JFXPanel();
fxContainer.setPreferredSize(new Dimension(JFXPANEL_WIDTH_INT, JFXPANEL_HEIGHT_INT));
add(fxContainer, BorderLayout.CENTER);
// create JavaFX scene
Platform.runLater(new Runnable() {
#Override
public void run() {
createScene();
}
});
}
private void createScene() {
JButton btn = new JButton();
btn.setText("Say 'Hello World'");
JRootPane root = new JRootPane();
root.getContentPane().add(btn);
fxContainer.setScene(new Scene(root));
}
}
This code works either as an applet or desktop app. here:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*;
// <applet code=TutoringCalculator width=400 height=400></applet>
public class TutoringCalculator extends JApplet {
// The size of an applet is set by the HTML!
//private static final int JFXPANEL_WIDTH_INT = 300;
//private static final int JFXPANEL_HEIGHT_INT = 250;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Tutoring Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet = new TutoringCalculator();
applet.init();
frame.setContentPane(applet.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
applet.start();
}
});
}
private JPanel swingContainer;
#Override
public void init() {
swingContainer = new JPanel(new BorderLayout());
add(swingContainer, BorderLayout.CENTER);
createScene();
}
private void createScene() {
JButton btn = new JButton();
btn.setText("Say 'Hello World'");
JRootPane root = new JRootPane();
root.getContentPane().add(btn);
swingContainer.add(root);
}
}
I could not be bothered figuring why you are using a RootPane so I left that as is.
Further tips
The spec. mentions JFrame but not JApplet. Since applets are significantly harder to develop, debug and deploy, I suggest you focus entirely on getting it working in a frame.
For frame positioning, you cannot go by setLocationByPlatform(true). See this answer for demo.

Categories

Resources