How to disable hiding of combobox popup in JavaFX8? - java

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

Related

JavaFX - switch stages and setX and setY of new stage

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.

How can I make a full screen java application?

I have an image viewer appplication. It works perfectly, but I'd like to make a full screen mode for it. It's an FXML project in Netbeans so, the main java is a separated file, therefore I cannot use this:
stage.setFullScreen(true);
because I can't reach the stage from my main .java file.
So I have a file, its name is imageViewer.java, it has this:
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("image_view.fxml"));
Scene scene = new Scene(root);
String css = this.getClass().getResource("style.css").toExternalForm();
scene.getStylesheets().add(css);
stage.setMinHeight(640);
stage.setMinWidth(960);
stage.setScene(scene);
stage.show();
}
and I have another file, it has fxml implements, and the ActionEvent void methods, you know, click the button, next picture etc...
The mentioned method (start method above) it's a method, therefore I can't return the stage. I have to reach the stage from image_viewController.java (the main java), what includes the other methods, functions and FXML implements etc...
I'd like to do this:
public void fullScreen(ActionEvent e) {
stage.setFullScreen(true);
}
But I can't reach the stage from another .java file. This is the first problem. And the second problem.
How can I make position absolute my panes, Vboxes etc like in html??? If my ImageView (what contains my image) get the full width and height, pulls down my HBox (what includes the buttons). If HBox were in absolute position, it wouldn't happened this, would it?
And the final problem, how can I make that, my HBox doesn't appear, just triggered by a hover effect. Is it possible with a separated css file? As I know, it is possible to make with FXML files.
Thanks for the answers!

How to refresh parent window after closing child window in JavaFX?

I have a parent Window which displays people i.e:
FirsName:John
LastName:Brown
Age:18
I click the Edit button, child window opens, change first name and then click accept, child window closes, the changes are in mysql database saved but the parent window still shows the old values. I do have a refresh method which works, but how can I call it from the child window or set it to be called after closing the child window?
Both Parent and Child Windows have controller and fxml. Any help would be appreciated.
James_D's Answer (better)
Thanks to #James_D, you should use setOnHidden instead of setOnCloseRequest, that way you can again just call .close() and the EventHandler will be called.
My Answer
You could make use of setOnCloseRequest:
childStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent we) {
// Refresh the parent window here
}
});
To invoke this close request on a child form you can do:
childStage.getOnCloseRequest().handle(new WindowEvent(childStage, WindowEvent.WINDOW_CLOSE_REQUEST));
// or
childStage.fireEvent(new WindowEvent(childStage, WindowEvent.WINDOW_CLOSE_REQUEST));
So you could implement the close button on the child stage like so:
Button closeButton = new Button("Close");
closeButton.setOnAction(event -> childStage.fireEvent(new WindowEvent(childStage, WindowEvent.WINDOW_CLOSE_REQUEST)));
I think the best way to have automatic field updates in JavaFX is by the use of properties. If the name field in the parent window is bound to a SimpleStringProperty you only need to set the property's value when the child window is closed to notify the parent window of the update.
I made a small parent / child example to test the concept and the relevant piece of code is this, placed on the child creation method:
FXMLLoader loader = new FXMLLoader(getClass().getResource("Child.fxml"));
Parent root = loader.load();
ChildController controller = loader.getController();
name.textProperty().bind(controller.name.textProperty());
The field name is a Label in the parent and a TextField in the child. Any change in the child's text is immediately reflected in the parent.
This is an interesting topic. I will make a full example and post ir in my 'a cup of java' blog as soon as possible.
If you use popup, you can set the method to showandwait instead of just show from the Stage object, and after run the method that update the GUI. Because showandwait method pause the main frame while the popup is running, once the popup closes it will run your update code.
stage.showAndWait();
updateGUI();
we think we have two stage(window),1-parent stage,2-child window(pop up window)
first send the stage object of parent stage to child stage
in child stage set :
childStage.setOnHidden(event->{
Parent root=FXMLLoader.load(getClass().getResource(parent fxml));
Scene scene=new Scene(root);
parentStage.SetScene(scene);
parentStage.show();
`

Creating a control seems to break transparent stages on JFX8

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;");

Determining window in which a menu item is clicked

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.

Categories

Resources