JAVA How to embed JAVAFX's label into a JPanel in swing? - java

How can I embed a custom label I created using JAVAFX into an existing swing's JPanel?
E.g.
Custom JavaFX Label:
public class CustomJavaFXLabel extends Label{
public CustomJavaFXLabel(){
super();
setFont("blah blah blah");
setText("blah blah blah");
/*
*and so on...
*/
}
}
Existing JPanel in swing
public class SwingApp(){
private JPanel jpanel;
public SwingApp(){
jpanel = new JPanel();
jpanel.add(new CustomJavaFXLabel()); //this line does not work
}
}
Error I got is:
The method add(Component) in the type Container is not applicable for argument (CustomJavaFXLabel)
I understand that to for this, I am better off using JLabel to create the custom label. However, due to certain constraints I was required to use FX for the custom Label.
Thanks.

As shown in JavaFX: Interoperability, ยง3 Integrating JavaFX into Swing Applications, add your custom javafx.scene.control.Label to a javafx.embed.swing.JFXPanel. Because a JFXPanel is a java.awt.Container, it can be added to your Swing layout. Several examples may be found here and below.
import java.awt.Dimension;
import java.awt.EventQueue;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javax.swing.JFrame;
/**
* #see https://stackoverflow.com/q/41159015/230513
*/
public class LabelTest {
private void display() {
JFrame f = new JFrame("LabelTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFXPanel jfxPanel = new JFXPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
};
initJFXPanel(jfxPanel);
f.add(jfxPanel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private void initJFXPanel(JFXPanel jfxPanel) {
Platform.runLater(() -> {
Label label = new Label(
System.getProperty("os.name") + " v"
+ System.getProperty("os.version") + "; Java v"
+ System.getProperty("java.version"));
label.setBackground(new Background(new BackgroundFill(
Color.ALICEBLUE, CornerRadii.EMPTY, Insets.EMPTY)));
StackPane root = new StackPane();
root.getChildren().add(label);
Scene scene = new Scene(root);
jfxPanel.setScene(scene);
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new LabelTest()::display);
}
}

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);
}
});
}
}

Java, Using javaFX for the main menu then switching over to JFrame for the game itself

I am here to ask if it is possible to use JavaFX for the main menu of my game and then switch over to JFrame for the game itself.
The reason I want to do this is because I know how to make pretty fancy game menus in JavaFX and not in JFrame and JavaFX to me also looks alot more fancy then JFrame..
I will truly appreciate any help you give me.
This can be done: you just need to make sure you use the correct threads for everything. In particular, ensure you launch the Swing application on the AWT Event Dispatch Thread.
Here is a simple example.
SwingApp:
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class SwingApp extends JFrame {
public SwingApp() {
setLayout(new BorderLayout());
add(new JLabel("This is the Swing App", JLabel.CENTER), BorderLayout.CENTER);
JButton quitButton = new JButton("Exit");
quitButton.addActionListener(e -> System.exit(0));
add(quitButton, BorderLayout.SOUTH);
setSize(600, 600);
setLocationRelativeTo(null);
setVisible(true);
}
}
and then
import javax.swing.SwingUtilities;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class LaunchSwingFromFX extends Application {
#Override
public void start(Stage primaryStage) {
Platform.setImplicitExit(false);
Button launch = new Button("Launch");
launch.setOnAction(e -> {
SwingUtilities.invokeLater(SwingApp::new);
primaryStage.hide();
});
StackPane root = new StackPane(launch);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

swing javafx application with undecorated frame

I don't understand completely how this doesn't work and I would like a fix to the problem if I could get one. I'm trying to get rid of the frame exit button, minimize, and restore, etc. so that I can set my own, but my program involves javafx and doesnt allow the setUndecorated() method to work.
import java.awt.Dimension;
import javax.swing.JFrame;
import javafx.application.Application;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Test extends JFrame {
private final int WIDTH = 600;
private final int HEIGHT = 300;
public Test() {
JFXPanel fxpanel = new JFXPanel();
fxpanel.setScene(createScene(this));
add(fxpanel);
setTitle("Frame");
setSize(new Dimension(WIDTH, HEIGHT));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
setLocationRelativeTo(null);
// setUndecorated(true); would go here.. but it doesn't work.
}
private Scene createScene(JFrame frame) {
StackPane root = new StackPane();
Scene scene = new Scene(root, Color.ALICEBLUE);
Text text = new Text();
text.setX(150);
text.setY(100);
text.setFont(new Font(25));
text.setText("Welcome JavaFX!");
root.getChildren().add(text);
return (scene);
}
public static void main(String[] args) {
new Test();
}
}
You have to call setUndecorated before setVisible

JScrollPane - content and Scrollbar not rendering

I'm creating a small Game of Life application. I'm using a 'dynamic universe' for all my cells (named Tiles in my project). But for some reason my JScrollPane and JButtons aren't rendering into the frame. I just get a empty JFrame. The controller is returning values and the buttons are getting constructed and added to the panel. It's just that jsp.setViewportView(p); doesn't seem to update the UI.
Main:
GOLController controller = new GOLController();
controller.run();
SwingUtilities.invokeLater(() -> {
GameOfLifeFrame frame = new GameOfLifeFrame(controller);
frame.init();
});
UI class:
package org.gameoflife.ui;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.gameoflife.controller.GOLController;
import org.gameoflife.model.Tile;
public class GameOfLifeFrame extends JFrame {
private final GOLController controller;
private JScrollPane jsp;
public GameOfLifeFrame(GOLController controller) throws HeadlessException {
super("Game of Life");
this.controller = controller;
}
public void init() {
jsp = new JScrollPane();
add(jsp);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setVisible(true);
controller.setLock();
this.draw();
controller.releaseLock();
}
public void draw(){
List<List<Tile>> currentState = controller.getTiles();
GridLayout layout = new GridLayout(currentState.size(), currentState.get(0).size());
JPanel p = new JPanel(layout);
currentState.stream().forEach((currentTiles) -> {
currentTiles.stream().map((t) -> {
JButton b=new JButton(" ");
b.setBackground(t.isHasLife() ? Color.GREEN : Color.BLACK);
return b;
}).forEach((b) -> {
p.add(b);
});
});
jsp.removeAll();
jsp.setViewportView(p);
}
}
I'm probably overlooking something really stupid, any help is appreciated.
This: jsp.removeAll() is going to be problematic, as it's likely removed the viewport AND the JScrollBars, it's also no required, as setting the viewportView will do the same thing anyway
Remember, JScrollPane is a specailsed component, that consists of a JViewPort and two JScrollBars, the actually content lives on the JViewport, not the JScrollPane

AWT Panel not getting rendered in JFX

I want to add a java.awt.Panel to my JavaFX8 application. Unfortunately it seems that the Panel doesn't get rendered when attached to a SwingNode.
I have a simple testapplication:
import java.awt.Dimension;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class AWTInJFX extends Application {
#Override
public void start(Stage stage) {
final AwtInitializerTask awtInitializerTask = new AwtInitializerTask(() -> {
AWTPanel panel = new AWTPanel();
return panel;
});
SwingNode swingNode = new SwingNode();
SwingUtilities.invokeLater(awtInitializerTask);
try {
swingNode.setContent(awtInitializerTask.get());
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(AWTInJFX.class.getName()).log(Level.SEVERE, null, ex);
}
stage.setScene(new Scene(new Group(swingNode), 600, 600));
stage.setResizable(false);
stage.show();
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setSize(new Dimension(600, 400));
frame.add(new AWTPanel());
frame.setVisible(true);
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
private class AwtInitializerTask extends FutureTask<JPanel> {
public AwtInitializerTask(Callable<JPanel> callable) {
super(callable);
}
}
}
My JPanel containing the java.awt.Panel
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Panel;
import javax.swing.JPanel;
public class AWTPanel extends JPanel{
public AWTPanel()
{
Dimension d = new Dimension(600, 400);
setPreferredSize(d);
Panel p = new Panel();
p.setSize(d);
p.setPreferredSize(d);
p.setBackground(Color.red);
this.add(p);
this.setBackground(Color.green);
}
}
Other AWT components doesn't show up either when I add my AWTPanel to a SwingNode.
Can somebody explain me why this isn't working?
I need a AWT Panel to get a hWnd used in additonal C++ libraries.
From the SwingNode Javadocs:
The hierarchy of components contained in the JComponent instance
should not contain any heavyweight components, otherwise SwingNode may
fail to paint it.
As far as I know, there is no way to embed a heavyweight component, such as an AWT component, in JavaFX.
Depending on your requirements, you could consider reversing things around, so that you have a Swing/AWT frame as your main window, and embed the JavaFX part of your application in a JFXPanel.

Categories

Resources