Playing around with my first JavaFX application. Running it on Java8 but that shouldn't be an issue regarding this question.
My problem:
I have a scene (FXML) in which a menu and menu items exist. When one presses a menu item a new window or popup should show. This works just fine, but I want to disable the parent window while the new window is active. Figured out this is possible with modality.
My real problem is: Determining the parent window from the action event I receive. Because the event comes from an menu item it seems a bit problematic. Probably a really stupid question.
My code snippet:
Stage stage = new Stage();
Parent root = FXMLLoader.load(EbooksdownloaderController.class.getResource("about.fxml"));
stage.setScene(new Scene(root));
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(((Node)event.getSource()).getScene().getWindow());
stage.show();
Casting the source to a Node gives a class casting exception. But I don't have a clue which other path to follow.
Thanks.
Have been fiddling around a while without any success.
As a final resort I finished it using the following code:
#FXML
private AnchorPane ap;
Stage stage = new Stage();
Parent root = FXMLLoader.load(EbooksdownloaderController.class.getResource("about.fxml"));
stage.setScene(new Scene(root));
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(ap.getScene().getWindow());
stage.show();
Not really the way I would prefer. But it works.
Related
I am familiarizing with JavaFX. I have created a loginStage and a mainStage. When pressing the 'Login' Button on the loginStage, I want to switch to the mainStage. The loginStage is a lot smaller than the mainStage. I want the mainStage to be located such that the former loginStage was positioned right in the middle of the mainStage (if we hadn't closed it).
I managed to switch from the loginStage to the mainStage. But for some reason the mainStage does not position itself correctly; it seems to me that its X- and Y-coordinate are not set at all!
Here is my code:
public void switchWindow() {
FXMLLoader loader = new FXMLLoader();
try {
Stage loginStage = (Stage) btnLogin.getScene().getWindow();
loginStage.setScene(null);
loginStage.hide();
Pane mainPane= (Pane) loader.load(getClass().getResource("/mainStage.fxml"));
Stage mainStage= new Stage();
mainStage.initStyle(StageStyle.TRANSPARENT);
Scene mainScene= new Scene(mainPane);
mainStage.setScene(mainScene);
mainStage.setX(loginStage.getX() + loginStage.getWidth()/2 - mainStage.getWidth()/2);
mainStage.setY(loginStage.getY() + loginStage.getHeight()/2 - mainStage.getHeight()/2);
mainStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
Also: I will be creating more stages. Hence, I figured it might be a good idea to create a switchWindow() function inside a separate package. I might just call the function with parameters oldStage and newPane. I wanted to ask you: What is the best practice of switching between stages? So that I do not reproduce the same code over and over again?
I figured it out - and yes, I am sorry, this seems to have been answered before.
The problem is that .getWidth() or .getHeight() methods can only be invoked AFTER the .show() method. Therefore, either change the order of calling the functions. This works fine - the mainStage seems to be at the correct x,y-coordinates from begin on. But to be sure that it does not get moved there after showing the stage, we could also just look up the width and the height of the mainStage inside the .fxml file and then substract these values in .setX() and .setY() respectively.
Is there a way to constantly show combobox popup? The question was about datepicker, but it is a descendant of combobox. I want to call show() method of combobox and then constantly show it until stage is closed.
The best thing that it got till now is
showingProperty().addListener({ ov, old, newValue ->
if (!newValue) this.show()
})
It kinda works, but it hides popup and then shows it, and that is inconvinient.
The bad solution
Take the popup content out of the date picker skin and use it like any other node. Note that the date picker itself must have been rendered as part of the scene at least once for the skin to have been initialized. There may be a more clever way to initialize the skin.
final DatePicker datePicker = new DatePicker();
final StackPane root = new StackPane( datePicker );
final Scene scene = new Scene( root, 250, 200 );
primaryStage.setScene( scene );
primaryStage.show();
datePicker.setVisible( false );
datePicker.setManaged( false );
final com.sun.javafx.scene.control.skin.DatePickerSkin skin = (com.sun.javafx.scene.control.skin.DatePickerSkin) datePicker.getSkin();
root.getChildren().add( skin.getPopupContent() );
Full example code at github.
The good solution
Use a control made specificly for your purpose, like CalendarPicker from JFXtras.
http://jfxtras.org/
If you could override the hide() method of the ComboBoxBase method, you would be able to prevent the control from closing. You would have to make a new class, like alwaysOpenDatePicker and let it extend the javafx scene datapicker class. In that class you could override the hide() method, in which you would do nothing.
I'm not sure if this would work, I'm just thinking out loud. I guess it's worth a try, let me know if it worked :).
And a link to the ComboBoxBase page:
https://docs.oracle.com/javafx/2/api/javafx/scene/control/ComboBoxBase.html
Switching between scenes; the Parent scene is smaller than the rest of the scenes, so when I go back to the first scene, the stage holds the With/Hight of the last scene. My code to switch to the parent scene is listed below, how can I set it to get the original size of the parent stage/scene? Thanks!!
public void goBack(MouseEvent e) throws IOException {
Stage stage;
Parent root;
root = FXMLLoader.load(getClass().getResource("Main.fxml"));
stage=(Stage) goBack.getScene().getWindow();
Scene scene = new Scene(root, 331, 181);
stage.sizeToScene();
stage.setScene(scene);
stage.show();
}
it looks like you are creating a new main scene. Its possible that you are not doing anything with that scene, and that is why nothing appears to be happening. Perhaps instead of doing this you should manually set the scene that already exists back to its original size. Without seeing the entire program I cant say for sure but this is a guess. Note also that it is unneccessary to generate a new main scene all the time. instead when switching scenes, the main scene should simply be set to invisible, until the program navigates back to it.
The above program should create a transparent stage with some text, but the stage appears opaque:
public class Test extends Application {
#Override
public void start(Stage primaryStage) {
new TextArea(); //Comment this out to enable transparency
Stage stage = new Stage();
stage.initStyle(StageStyle.TRANSPARENT);
Text text = new Text("Is this transparent?");
VBox box = new VBox();
box.getChildren().add(text);
final Scene scene = new Scene(box, 300, 250);
scene.setFill(null);
stage.setScene(scene);
stage.show();
}
}
The new TextArea() line is what breaks things - comment that out and it all works.
Creating any subclass of control (even via new Control() {};) breaks things - a Region or above does not.
This doesn't occur in Java 7 / JFX2.x.
I've created a JIRA for this since it seems a very obvious regression (https://javafx-jira.kenai.com/browse/RT-38938), but is anyone aware why this happens and thus how to work around it until a fix is provided? I've tried replicating this issue by copying the code in Control's constructor, but this seems to be fine - it's just instantiating Control itself that seems to break things.
I remember some forum discussion on this. I think the general gist is that creating a control forces css to be applied to the layout pane, and the layout pane is getting the opaque background.
As a workaround, make the background of the layout pane transparent:
box.setStyle("-fx-background-color: transparent;");
I want to create an Fullscreen Application on an RasperryPI.
But now i have a problem with the fullscreen mode, because everytime if I switch sites I must set the FullSreen property false and then true otherwise the window won't get fullscreen.
But if I switch the site the window is shortly not fullscreen and the it is fullscreen.
SplitPane splitPane = new SplitPane();
splitPane.setOrientation(Orientation.VERTICAL);
splitPane.getItems().addAll(table,vbLayout);
Scene scene = SceneBuilder.create().root(splitPane). build();
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.sizeToScene();
primaryStage.setFullScreen(false);
primaryStage.setFullScreen(true);
I hope you understand what i mean.
Best wishes
Johannes
You should not be able to switch sites when you are in fullscreen mode. If you are able to, you must first stop it. The user must come back to normal mode before doing anything else or you must force the normal mode. It's just like playing a video on fullscreen mode on youtube.
You Can Use Follwing Code:-
I Have Use Rectangle 2D Class
SplitPane splitPane = new SplitPane();
splitPane.setOrientation(Orientation.VERTICAL);
splitPane.getItems().addAll(table,vbLayout);
Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
Scene scene = SceneBuilder.create().root(splitPane). build();
scence.setWidth(primScreenBounds.getWidth());
scence.setHeight(primScreenBounds.getHeight())
primaryStage.setScene(scene);
primaryStage.show();