Issue
Minimal classes to reproduce the issue:
import static com.gluonhq.charm.glisten.application.AppManager.*;
import javafx.application.Application;
import javafx.stage.Stage;
import com.gluonhq.charm.glisten.application.AppManager;
import com.gpsdemo.view.View1;
import com.gpsdemo.view.View2;
public class MyApplication extends Application {
AppManager appManager = AppManager.initialize();
public static final String VIEW1 = HOME_VIEW;
public static final String VIEW2 = "View2";
@Override
public void init() {
appManager.addViewFactory(VIEW1, View1::get);
appManager.addViewFactory(VIEW2, View2::get);
}
@Override
public void start(Stage stage) throws Exception {
appManager.start(stage);
if (com.gluonhq.attach.util.Platform.isDesktop()) {
stage.setHeight(600);
stage.setWidth(360);
stage.centerOnScreen();
}
}
public static void main(String args[]) {
launch(args);
}
}
import javafx.scene.control.Label;
import com.gluonhq.charm.glisten.control.AppBar;
import com.gluonhq.charm.glisten.mvc.View;
import com.gluonhq.charm.glisten.visual.MaterialDesignIcon;
import com.gpsdemo.MyApplication;
public class View1 extends View {
private static View1 INSTANCE;
public static View1 get() {
return INSTANCE != null ? INSTANCE : (INSTANCE = new View1());
}
private View1() {
setCenter(new Label("Nothing to see here"));
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setTitleText("View1");
var optionsButton = MaterialDesignIcon.MENU.button(e -> getAppManager().switchView(MyApplication.VIEW2));
appBar.getActionItems().add(optionsButton);
}
}
import java.util.Set;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Node;
import com.gluonhq.charm.glisten.control.AppBar;
import com.gluonhq.charm.glisten.control.SettingsPane;
import com.gluonhq.charm.glisten.control.settings.DefaultOption;
import com.gluonhq.charm.glisten.mvc.View;
import com.gluonhq.charm.glisten.visual.MaterialDesignIcon;
public class View2 extends View {
private static View2 INSTANCE;
public static View2 get() {
return INSTANCE != null ? INSTANCE : (INSTANCE = new View2());
}
private View2() {
var settingsPane = new SettingsPane();
var option = new DefaultOption<>("Title", "Description", "Category", new SimpleDoubleProperty(), true);
settingsPane.getOptions().add(option);
setCenter(settingsPane);
setOnShown(e -> {
System.out.println("On shown");
Set<Node> lookup = settingsPane.lookupAll(".secondary-graphic");
System.out.println(lookup);
});
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setTitleText("View2");
var backButton = MaterialDesignIcon.ARROW_BACK.button(e -> getAppManager().switchToPreviousView().get());
appBar.setNavIcon(backButton);
}
}
Launch the application normally, View1
will show.
Click on the button to show View2
. The first time View2
is loaded the output is
On shown
[]
So the lookup
fails in the onShown
event.
Click on the back button and then show View2
again. The output is
On shown
[HBox@2c8d8a10[styleClass=secondary-graphic]]
which is correct.
If View2
is set as HOME_VIEW
, the lookup will find the nodes correctly on the first onShown
event. This looks like a bug to me. Regardless, I would like the lookup to succeed on the first time so I can configure the view correctly.
Using:
<javafx-maven-plugin-version>0.0.8</javafx-maven-plugin-version>
<gluonfx-maven-plugin-version>1.0.14</gluonfx-maven-plugin-version>
<java-version>17</java-version>
<javafx-version>18.0.1</javafx-version>
<charm-version>6.1.0</charm-version>
Solution
As mentioned in the comments, the issue is that the SHOWN
event does not happen after a css pass is applied, therefore the lookup fails. A fix can be to manually do a css pass before the lookup, inside the SHOWN
handler:
setOnShown(e -> {
System.out.println("On shown");
settingsPane.applyCss();
Set<Node> lookup = settingsPane.lookupAll(".secondary-graphic");
System.out.println(lookup);
});
This is confusing because the SHOWN
event does not actually happen after the view is fully shown (in which case a css pass has happened). The event also behaves differently than JavaFX's dialog DIALOG_SHOWN
event, that does happen after the dialog is fully shown (including a css pass).
Answered By - user1803551
Answer Checked By - Candace Johnson (JavaFixing Volunteer)