Swing Content breaking in FX TabPane - java

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

Related

How to set an action to occur whenever JFXPanel is closed?

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

Why is it not displaying my button?

I am trying to use a layered pane to make a menu for a program I'm working on, but the button won't display. I can't seem to figure out what it is...
public class FlashcardGUI {
public static void main(String[] args)
{
JFrame projectFrame = new JFrame("StudyFast Flashcard");
projectFrame.setName("StudyFast Flashcards");
projectFrame.setSize(1000,600);
projectFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
projectFrame.setVisible(true);
JLayeredPane projectLayeredPane = new JLayeredPane();
projectFrame.setContentPane(projectLayeredPane);
JPanel projectMenu1 = new JPanel();
projectLayeredPane.setLayer(projectMenu1, 0);
final JButton startNow = new JButton();
startNow.setText("Exit");
startNow.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
projectFrame.add(projectLayeredPane);
projectLayeredPane.add(projectMenu1);
projectMenu1.add(startNow);
}
}
Put these two lines at the end of your main method. The order is important in order to make the button display.
projectFrame.pack();
projectFrame.setVisible(true);
(Make sure to remove the projectFrame.setVisible(true); you already have on line 9.)
I have updated your code and it is working now. Please see the inline comments for the issue in your code. Hope this helps.
public class FlashcardGUI2 {
public static void main(String[] args) {
JFrame projectFrame = new JFrame("StudyFast Flashcard");
projectFrame.setName("StudyFast Flashcards");
projectFrame.setSize(1000,600);
projectFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
projectFrame.setVisible(true);
JLayeredPane projectLayeredPane = new JLayeredPane();
LayoutManager layout = new FlowLayout(); //creating a FlowLayout object
projectLayeredPane.setLayout(layout); //adding the layout to JLayeredPane
//because JLayeredPane do not have default layout of
//its own. The reason you were not
//getting the button displayed
projectLayeredPane.setPreferredSize(new Dimension(300, 310));
JPanel projectMenu1 = new JPanel();
final JButton startNow = new JButton();
startNow.setText("Exit");
startNow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
projectLayeredPane.add(projectMenu1,new Integer(50));
projectLayeredPane.add(startNow,new Integer(10));
projectFrame.add(projectLayeredPane);
projectFrame.pack();
}
}

javaFX launch app error

i'm trying to run this simple Javafx code:
public class Javafx extends Application
{
Stage window;
Scene scene1,scene2;
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) throws Exception{
window = primaryStage;
Label label1 = new Label("click here to go to scene 2");
Button button1 = new Button("click here");
button1.setOnAction(e-> window.setScene(scene2));
VBox layout1 = new VBox(15);
layout1.getChildren().addAll(label1,button1);
scene1 = new Scene(layout1,700,900);
Label label2 = new Label("get back to scene1");
Button button2 = new Button("press");
button2.setOnAction(e-> window.setScene(scene1));
StackPane layout2 = new StackPane();
label2.setRotate(70);
layout2.getChildren().addAll(label2,button2);
scene2 = new Scene(layout2,500,500);
window.setScene(scene1);
window.setTitle("Java FX");
window.show();
}
}
but for some reason after i'm closing the app and rerun it,iv'e got an error:
application luanch must not called more than once.
as far as i can tell,the launch app called only once,but the only way for me to rerun it again is to reset first the JVM .
can anyone tell me how can i overcome this?
i'm using Bluej if that's matter,

How to Achieve One Menubar for more then one scenes in javaFx

I am basically new to Java FX 2.
Scenario:
I have 3 Scenes and I want a way to add menu-bar such that I don't i don't want to explicitly remove the menu bar from previous scene and add it to new one. Like Some thing a Parent Scene or some way menu-bar is attached to Stage. I mean menu-bar is added just one time and always be present whatever scene is in front or not.
If This is Possible How Can I do this.
Here is the Default Example Provided by Oracle Docs of JavaFX http://docs.oracle.com/javafx/2/ui_controls/MenuSample.java.html
public class Main extends Application {
final ImageView pic = new ImageView();
final Label name = new Label();
final Label binName = new Label();
final Label description = new Label();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
stage.setTitle("Menu Sample");
Scene scene = new Scene(new VBox(), 400, 350);
scene.setFill(Color.OLDLACE);
MenuBar menuBar = new MenuBar();
// --- Graphical elements
final VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.setPadding(new Insets(0, 10, 0, 10));
makeContentsForVBox();// in this vBox area will be fill with name pic desrciption
vbox.getChildren().addAll(name, binName, pic, description); // name is lable
// --- Menu File
Menu menuFile = new Menu("File");
MenuItem add = new MenuItem("Shuffle",
new ImageView(new Image(getClass().getResourceAsStream("new.png"))));
add.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
shuffle();
vbox.setVisible(true);
}
});
MenuItem clear = new MenuItem("Clear");
clear.setAccelerator(KeyCombination.keyCombination("Ctrl+X"));
clear.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
vbox.setVisible(false);
}
});
MenuItem exit = new MenuItem("Exit");
exit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
System.exit(0);
}
});
menuFile.getItems().addAll(add, clear, new SeparatorMenuItem(), exit);
((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);
stage.setScene(scene);
stage.show();
}
}
So Here menuBar is added to a scene. if i swap the scene and bring an other scene in front ... What will i do. i think I remove menuBar from this scene and add to other or simply add to new one. so every time i have to do this when i change. Is there any way to avoid this??
The approach I would prefer is to use a Scene with BorderPane as its root
scene.setRoot(borderPane);
You can add the MenuBar to the top of the BorderPane and at its Center you can place SplitPane
BorderPane borderPane = new BorderPane();
borderPane.setTop(menuBar);
borderPane.setCenter(splitPane);
Whenever you need to switch to WebView just replace it with SplitPane :
borderPane.setCenter(webView);
Following this approach, your MenuBar will always remain on TOP and you can switch between SplitPane and WebView

JavaFX 2.0 SplitPane no longer working as expected

Since updating to JavaFX 2.0 b36 (SDK for Windows (32Bit) + Netbeans Plugin) from a previous JavaFX 2.0 version the SplitPane control does not work as expected any longer.
The divider can't be moved
The divider position is not as expected
The sizing of the contained sides is not as expected
Here my example code for a SplitPane .
public class FxTest extends Application {
public static void main(String[] args) {
Application.launch(FxTest.class, args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("SplitPane Test");
Group root = new Group();
Scene scene = new Scene(root, 200, 200, Color.WHITE);
Button button1 = new Button("Button 1");
Button button2 = new Button("Button 2");
SplitPane splitPane = new SplitPane();
splitPane.setPrefSize(200, 200);
splitPane.setOrientation(Orientation.HORIZONTAL);
splitPane.setDividerPosition(0, 0.7);
splitPane.getItems().addAll(button1, button2);
root.getChildren().add(splitPane);
primaryStage.setScene(scene);
primaryStage.setVisible(true);
}
}
As you can (hopefully) see the left side is clearly smaller than the right side.
Another funny fact is, when you change orientation to VERTICAL
splitPane.setOrientation(Orientation.VERTICAL);
and try to move the divider up or down you get some console output saying 'HERE'.
Looks like some test output.
What's the issue with this?
To get the SplitPane working as expected add a layout (e.g. BorderPane) to each side. Add the controls to display to each of these layouts. I think this should be made more clear in API documentation!
public class FxTest extends Application {
public static void main(String[] args) {
Application.launch(FxTest.class, args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("SplitPane Test");
Group root = new Group();
Scene scene = new Scene(root, 200, 200, Color.WHITE);
//CREATE THE SPLITPANE
SplitPane splitPane = new SplitPane();
splitPane.setPrefSize(200, 200);
splitPane.setOrientation(Orientation.HORIZONTAL);
splitPane.setDividerPosition(0, 0.7);
//ADD LAYOUTS AND ASSIGN CONTAINED CONTROLS
Button button1 = new Button("Button 1");
Button button2 = new Button("Button 2");
BorderPane leftPane = new BorderPane();
leftPane.getChildren().add(button1);
BorderPane rightPane = new BorderPane();
rightPane.getChildren().add(button2);
splitPane.getItems().addAll(leftPane, rightPane);
//ADD SPLITPANE TO ROOT
root.getChildren().add(splitPane);
primaryStage.setScene(scene);
primaryStage.setVisible(true);
}
}

Categories

Resources