TomDK
TomDK

Reputation: 1411

Hide and Show JavaFX chart in Swing

Hi would like to share my Warkaround to a problem that has been taken me hours to solve as I couldn't find any straight forward answer.

I'm implementing a Swing application that depending on its status, either shows a JavaFX Chart (a live line chart) or some other content (in my case it was a JFreeChart). I was add and removing the panel to my UI which works fine with most content however.

When using JavaFX, my content would not show up once it has been visible and then hidden.

See non working sample code below:

CustomFXPanel pn1 = new CustomFXPanel(); //JPanel containing JavaFX Chart
CustomPanel pn2 = new CustomPanel();     //Extends JPanel
JPanel pnContent; //PlaceHolder for either Panel



/**
 * Constructor
 */
public MyJFrame(){
    init(); //Set up JFrame Size, title etc.
    setLayout(new GridLayout(1,1)); //Show the Content all across the Frame
    pnContent = pn1;
    add(pnContent);
}    

/**
 * Changes Mode of Application
 * @param showFX: True = show fxChart, False = show other Panel
 */
public void changePanel(boolean showFX){
    if(showFX){  //Show FX Chart
        if(!pnContent.equals(pn1)){
            remove(pnContent);
            pnContent = pn1;
            add(pnContent);
        }
    }else{  //Show other Panel
        if(!pnContent.equals(pn2)){
            remove(pnContent);
            pnContent = pn2;
            add(pnContent);
        }
    }
}

The Problem: It will display fine upon startup. However, when changing to pn2 and then back to pn1 the JFXPanel inside pn1 would simply not show up.

I got it working by reCalling myFXPanel.setStage(new Stage(myJFXChart)) inside pn1. However this always threw an IllegalArgumentsException, ..."already set as root of another scene". - It worked but I think having Exception flying around is ugly and bad practice.

Annoyingly, any attempt of dealing with this Exception resulted in the Panel not showing up again. This includes:

JFXPanel myFXPanel = new JFXPanel();
LineChart<Number, Number> chart;
....
//Inside reload method
//With parts inside then outside Platform.runLater(new Runnable()) {...}
myFXPanel.invalidate();
myFXPanel.removeAll();
try{
    setStage(newStage(chart));
}catch(Exception ex){}

Upvotes: 1

Views: 808

Answers (1)

TomDK
TomDK

Reputation: 1411

The only workaround I could find is by abusing a JSplitPane (setDivider(0) and set either side as setVisible(false)): Sample Code as follows.

CustomFXPanel pn1 = new CustomFXPanel(); //JPanel containing JavaFX Chart
CustomPanel pn2 = new CustomPanel();     //Extends JPanel
JSplitPane spContent;
…
/**
 * Constructor
 */
public MyJFrame(){
    init(); //Set up JFrame Size, title etc.
    spContent.setDividerSize(0);        //Hide the Divider
    spContent.setLeftComponent(pn1);    
    spContent.setLeftComponent(pn2);
    pn1.setVisible(true);               //By default show pn1
    pn2.setVisible(false);              //Hide this Panel. JSplitPane will adjust itself (either left or right will take up all space).

    setLayout(new GridLayout(1,1)); //Show the Content all across the Frame
    add(spContent);
}    

/**
 * Changes Mode of Application
 * @param showFX: True = show fxChart, False = show other Panel
 */
public void changePanel(boolean showFX){
    if(showFX){  //Show FX Panel
        pn1.setVisible(true);    //spContent will adjust itself
        pn2.setVisible(false);
    }else{  //Show normal Panel
        pn1.setVisible(false);
        pn2.setVisible(true);
    }
}

If any of you find a more elegant solution to this please feel free to write down your answer. I have written my own workaround in here as I think, I'm not the only one who has/had this issue.

I hope I could help. Cheers

Upvotes: 1

Related Questions