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
Related
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);
}
});
}
}
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);
}
}
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);
}
}
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);
}
}
I created a set of JavaFX components in a Scene which I'd like to display in a resizable modal dialog in a swing applications. The JavaFX components include ImageViews for scanned images which can get quite big dependening on the zoom level, so precise layouting in an issue. My options are afaik
displaying a JavaFX Dialog with showAndWait in a Platform.runLater and stop the Swing EDT with an invisible JDialog. That apparently causes deadlocks and is quite unelegant.
put the JavaFX components in a JFXPanel and display it in a JDialog. That works in terms of modality, but I have no idea how to layout components in the JFXPanel since in a GroupLayout the panel simply grows infinitely (JavaFX ScrollPane don't have any effect).
For example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class NewMain1 extends Application {
private final ImageView imageView;
public NewMain1() {
this.imageView = new ImageView(NewMain.class.getResource("/File_CC-BY-SA_3_icon_88x31.png").toString());
}
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
BorderPane borderPane = new BorderPane();
Button bottomButton = new Button("Some button");
ScrollPane imageViewScrollPane = new ScrollPane(imageView);
borderPane.setCenter(imageViewScrollPane);
borderPane.setBottom(bottomButton);
imageView.setSmooth(true);
imageView.setFitHeight(400);
StackPane root = new StackPane();
root.getChildren().add(borderPane);
stage.setScene(new Scene(root, 800, 600));
stage.show();
}
}
shows a well working ScrollPane for the ImageView whereas in a JFXPanel in a JDialog the scrolling/layout doesn't work:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.HeadlessException;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class NewMain extends JFrame {
private static final long serialVersionUID = 1L;
private final JFXPanel mainPanel = new JFXPanel();
private final ImageView imageView;
private final JButton closeButton = new JButton("Close");
public NewMain() throws HeadlessException {
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setBounds(0, 0, 800, 600);
setPreferredSize(new Dimension(800, 600));
GroupLayout layout = new GroupLayout(this.getContentPane());
this.getContentPane().setLayout(layout);
layout.setAutoCreateContainerGaps(true);
layout.setAutoCreateGaps(true);
this.imageView = new ImageView(NewMain.class.getResource("/File_CC-BY-SA_3_icon_88x31.png").toString());
Platform.runLater(() -> {
BorderPane borderPane = new BorderPane();
Button bottomButton = new Button("Some button");
ScrollPane imageViewScrollPane = new ScrollPane(imageView);
borderPane.setCenter(imageViewScrollPane);
borderPane.setBottom(bottomButton);
imageView.setSmooth(true);
imageView.setFitHeight(400);
Group root = new Group();
Scene scene = new Scene(root, Color.ALICEBLUE);
root.getChildren().add(borderPane);
mainPanel.setScene(scene);
});
closeButton.addActionListener((event) -> {
setVisible(false);
});
layout.setHorizontalGroup(layout.createParallelGroup()
.addComponent(mainPanel)
.addComponent(closeButton));
layout.setVerticalGroup(layout.createSequentialGroup()
.addComponent(mainPanel)
.addComponent(closeButton));
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new NewMain().setVisible(true);
});
}
}
Don't make the root of the Scene a Group, Groups are not resizable.
Just remove the group and use a resizable layout for the scene root (you already have a resizable layout in your sample code, it's the BorderPane, so you can just use that).
Instead of:
Group root = new Group();
Scene scene = new Scene(root, Color.ALICEBLUE);
root.getChildren().add(borderPane);
Write:
Scene scene = new Scene(borderPane, Color.ALICEBLUE);
ScrollPane inside a JavaFX scene inside a JFXPanel inside a Swing JFrame.
Note, that in your pure JavaFX NewMain1 application, you use are already using a resizable pane as a root (a StackPane), so that is the reason for the discrepancy that you observed between the pure JavaFX version and the Swing embedded version.