I have an application built on Swing integrated with JavaFX. Swing's JFrame is the top-level window, with JFXPanel housing different JavaFX controls. Now, I am also integrating JavaFX's new Alert API, and currently having difficulty in setting Alert's ownership when shown. That is, I would like to make JFrame as the owner of Alert.
JFXPanel fxPanel = new JFXPanel();
Platform.runLater(() -> {
Button button = new Button("Alert");
button.setOnAction(evt -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("An Alert");
alert.setContentText("Alerting");
alert.initModality(Modality.APPLICATION_MODAL);
alert.initOwner(button.getScene().getWindow());
alert.initStyle(StageStyle.UTILITY);
alert.show();
});
BorderPane borderPane = new BorderPane();
borderPane.setCenter(button);
Scene scene = new Scene(borderPane, 300, 300);
SwingUtilities.invokeLater(() -> {
fxPanel.setScene(scene);
JFrame frame = new JFrame("App");
frame.add(fxPanel);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
});
I understand that when a window reference is taken in this code alert.initOwner(button.getScene().getWindow());, com.sun.javafx.stage.EmbeddedWindow object is returned. I know that it would be impossible to take JFrame as the window owner of Alert. But, is there a hack to make this happen?
Look here:
http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/swing-fx-interoperability.htm
It says something like this ->
JFrame frame = new JFrame("Swing and JavaFX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
Related
I'm building a Swing application and I'm using JFXPanel to bring up a WebView for user authentication. I need to return the url that the WebEngine is sent to after a successful user sign-on- but I don't know how to pull the URL from the view at the time the window is closed. I'm aware of Stage.setOnHiding, but this can't apply here since JFXPanels don't act as stages, though they contain a scene.
I'm very new to JavaFX so if this code snippet demonstrates bad conventions, I'd be happy to hear it!
private static void buildAuthBrowser() {
JFrame frame = new JFrame("frame");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Platform.runLater(new Runnable() {
#Override
public void run() {
initFX(fxPanel);
}
});
}
private static void initFX(JFXPanel fxPanel) {
// fx thread
Scene scene = createScene();
fxPanel.setScene(scene);
}
private static Scene createScene() {
Group root = new Group();
Scene scene = new Scene(root);
WebView view = new WebView();
WebEngine browser = view.getEngine();
browser.load(auth.getUrl());
root.getChildren().add(view);
return (scene);
}
Found a solution- I was able to set a listener on the engine in the scene builder method, this way, every time the browser visits a new URL it automatically updates a private variable.
in createScene():
authBrowser.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
if (Worker.State.SUCCEEDED.equals(newValue)) {
setCode(authBrowser.getLocation());
}
});
I am working on a project that requires loading already existing complex Swing Content inside a UI built in FX. The problem i get is, that the Swing Content constantly "breaks" leaving the corresponding Swing Node / FX Pane empty. I have built a minimal working code example to partly reproduce the problem. When resizing the window containing 3 Tabs, the only Swing Node that shows properly is the one in the currently selected tab. Usually both other tabs "break".
public class Main extends Application {
private final SwingNode node1 = new SwingNode();
private final SwingNode node2 = new SwingNode();
private final SwingNode node3 = new SwingNode();
#Override
public void start(Stage primaryStage) {
try {
TabPane root = new TabPane();
Tab tab1 = new Tab("Tab 1");
Tab tab2 = new Tab("Tab 2");
Tab tab3 = new Tab("Tab 3");
createAndSetSwingContent();
tab1.setContent(node1);
tab2.setContent(node2);
tab3.setContent(node3);
root.getTabs().add(tab1);
root.getTabs().add(tab2);
root.getTabs().add(tab3);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private void createAndSetSwingContent() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JPanel panel1 = new JPanel(new BorderLayout());
JPanel panel2 = new JPanel(new BorderLayout());
JPanel panel3 = new JPanel(new BorderLayout());
JButton btn1 = new JButton("Button 1");
JButton btn2 = new JButton("Button 2");
JButton btn3 = new JButton("Button 3");
panel1.add(btn1);
panel2.add(btn2);
panel3.add(btn3);
node1.setContent(panel1);
node2.setContent(panel2);
node3.setContent(panel3);
}
});
}
public static void main(String[] args) {
launch(args);
}
}
Is this problem reproducable for anyone else? And is this a java bug, or am i missing something in my code? I am using Java 11 and JavaFX 11 in eclipse. I included the JavaFX11 jars as a User Library in the Classpath, and added the following VM Arguments in Run Configurations:
--module-path "C:\JavaFX\javafx-sdk-11.0.2\lib" --add-modules javafx.controls,javafx.fxml,javafx.swing
Reminds me on an issue I had some years ago with JFXPanel - have you already tried Platform#setImplicitExit(false)?
Example:
Platform.setImplicitExit(false);
Platform.runLater(new Runnable(){
public void run(){
createScene();
}
});
I'm trying to learn javafx and I'm having some trouble with alert box interactions. My code is pretty straightforward:
public static void display(String title, String message) {
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle(title);
window.setMinWidth(250);
Label label = new Label();
label.setText(message);
Button closeButton = new Button("Close the window");
closeButton.setOnAction(e -> window.close());
VBox layout = new VBox(10);
layout.getChildren().addAll(label, closeButton);
layout.setAlignment(Pos.CENTER);
Scene scene = new Scene(layout);
window.setScene(scene);
window.showAndWait();
}
The problem is I can still somewhat interact with my initial window that I used to open the alert box, mainly clicking on the initial window brings it in front of the alert box. To my understanding, this shouldn't happen. Here is a gif demonstrating the issue: https://gyazo.com/0c2b69ec39f849227560fbdf2099c07c
Here is my code that calls the alert box
public void start(Stage primaryStage) {
window = primaryStage;
window.setTitle("Alert Box test");
button = new Button("Click me");
button.setOnAction(e -> AlertBox.display("New Alert", "Don't forget to close this window!"));
StackPane layout = new StackPane();
layout.getChildren().add(button);
Scene scene = new Scene(layout, 300, 250);
window.setScene(scene);
window.show();
}
What am I doing wrong here or is that just the intended behavior?
I can't seem to find any information on this, is it possible to use JxBrowser to display a webpage and java swing controls within the same frame and if so, how? My current code is just one to display a window with google maps currently as I keep trying things and deleting them.
public static void main(String[] args) {
Browser browser = new Browser();
BrowserView view = new BrowserView(browser);
JFrame frame = new JFrame("Google Maps");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
frame.setSize(1500,1000);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
browser.loadURL("http://maps.google.com");
}
BrowserView that you embed into a frame is a Swing component. You can add other Swing components in the same way:
public static void main(String[] args) {
Browser browser = new Browser();
BrowserView view = new BrowserView(browser);
JFrame frame = new JFrame("Google Maps");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
// Let's add a button
frame.add(new JButton("My Button"), BorderLayout.SOUTH);
frame.setSize(1500,1000);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
browser.loadURL("http://maps.google.com");
}
I'm working on an application which is based on swing and javafx 8. In this create a frame in swing and jbutton use and jbutton action code is done in javafx 8 means use scene. in this a alert dialog create.but problem is that if i click anywhere except alert dialog then alert dialog hidden behind swing frame.i want javafx alert dialog keep on swing frame which i create.if i click ok on alert then action is goes to swing frame.
please suggest......
here is my code:
final JFXPanel fxPanel = new JFXPanel();
Platform.runLater(new Runnable() {
public void run() {
initFX(fxPanel);
}
private void initFX(JFXPanel fxPanel) {
// TODO Auto-generated method stub
Scene scene = createScene();
fxPanel.setScene(scene);
}
private Scene createScene() {
Group root = new Group();
Scene scene = new Scene(root);
Alert cn=new Alert(AlertType.CONFIRMATION);
cn.initStyle(StageStyle.UNDECORATED);
cn.setTitle(null);
cn.setHeaderText(null);
cn.setContentText(ProjectProps.rb.getString("msg.play.confirm"));
DialogPane dp=cn.getDialogPane();
dp.getStylesheets().add(getClass().getResource("login.css").toExternalForm());
dp.setStyle("-fx-border-color: black; -fx-border-width: 5px; ");
Optional<ButtonType> result=cn.showAndWait();
if(result.get()==ButtonType.OK){
System.out.println("ok button clicked:"+result.get());
k=0;
} else{
System.out.println("cancel clicked");
k=1;
}
return (scene);
}
});
I'm not sure to understand what you really want to do. Do you absolutely need a JavaFX alert in a swing application? JDialog works very well, and Alert and Dialogs works very well too in a JavaFX context.
Have you tried to set your Alert application modal with cn.initModality(Modality.APPLICATION_MODAL) ?
Maybe you can find you answer in this post : How to make a JFrame Modal in Swing java
This is the suggested code in the post:
final JDialog frame = new JDialog(parentFrame, frameTitle, true);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
I would create a new JDialog and set as parameter your main frame (parentFrame) and add your JFXPanel to its content.
frame.getContentPane.add(fxPanel)
You can use fxPanel.setScene(yourScene) to add FX content to your JDialog.
Example for the suggestion:
public class Main {
public static void main(String[] args) {
// create parent
JFrame parent = new JFrame("MainFrame");
parent.setSize(500, 500);
// center of screen
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
parent.setLocation(dim.width/2-parent.getSize().width/2, dim.height/2-parent.getSize().height/2);
parent.setVisible(true);
createDialog(parent);
}
private static void createDialog(JFrame parent) {
// create dialogs JFX content
BorderPane layout = new BorderPane();
layout.setTop(new Button("HELLO"));
layout.setBottom(new Button("IT'S ME"));
Scene scene = new Scene(layout);
JFXPanel dlgContent = new JFXPanel();
dlgContent.setScene(scene);
dlgContent.setPreferredSize(new Dimension(200, 200));
dlgContent.setVisible(true);
// create dialog and set content
JDialog dlg = new JDialog(parent, "Dialog", true);
dlg.setLocationRelativeTo(parent);
dlg.getContentPane().add(dlgContent);
dlg.pack();
dlg.setVisible(true);
}
}
Hope I could help you.