i have to make a game for a school project and i was wondering if it's possible to lock a screen in a certain position on the screen. I have a settings button that opens a new stage and i want to make that scene immovable is this possible?
This is the code where i display the settings screen:
Public void buttonAction(){
btnSettings.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
GridPane settingsGrid = new GridPane();
Scene scene1 = new Scene(settingsGrid,375,600);
Stage settingsStage = new Stage();
settingsGrid.setHgap(10);
settingsGrid.setVgap(10);
//settingsGrid.setGridLinesVisible(true);
settingsStage.setTitle("Settings");
settingsStage.setResizable(false);
settingsStage.initStyle(StageStyle.UTILITY);
settingsStage.initModality(Modality.APPLICATION_MODAL);
settingsStage.setScene(scene1);
settingsStage.showAndWait();
}
});
}
Thanks in advance!
you could try this:
settingsStage.initStyle(StageStyle.TRANSPARENT);
However, you could only have one initStyle if I remember correctly. So you have to settingsStage.initStyle(StageStyle.UTILITY); in order to use the above code. What it does is it make the background transparent and the user could not change the position.
Related
I'm currently trying to show a BorderPane inside my AnchorPane (that is also inside my StackPane). I tried to show a new Scene but it show me 2 items in my Windows taskbar, and this is not really what I want.
For exemple, when you open the Preference in Eclipse, u get another window that is not visible in the taskbar.
So basically, the only thing I need is a window that looks like an ImageView, like anchored in the AnchorPane , not resizable and undecorated.
Expected result at end
This is what I tried:
btnDice.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent arg0) {
Scene newScene = new Scene(new BorderPane(), 230, 100);
Stage newWindow = new Stage();
newWindow.setScene(newScene);
newWindow.show();
}
});
The title may be a bit vague, so allow me to define it a little better. I have a working piece of code (down below): a simple main menu for a game I am working on. Everything works well, except for the Start button.
What I want to be able to do is click the Start button, and have a new scene appear on the same stage (window). I do not want to see a new window open. I have talked with someone more experienced in Java, and they told me to create separate classes for the MenuFX and the GameFX. If that is the case, I would need to call some start or launch method on the GameFX class from the MenuFX class, correct? Is this the best approach, or would I want to keep all FX-related code in one class? Also, I should keep the same stage for all FX work, no?
This post shed some light on things, but I am not well-versed in some of the terms discussed- for instance, I still do not understand the concept of Root.
Also, this post talks about a similar application, but I am not using FXML or SceneBuilder... I do not know if any of it is relatable.
MenuFX.java - I have removed some of the working code, simply for brevity. You can see that all I need help with is tying the Start button to some functionality that makes a new empty scene.
/*
* This is simply working on the title screen.
*/
// Asssume all imports are correct
import java.everythingNeeded
public class MenuFX extends Application {
#Override
public void start (Stage primaryStage) {
// Make the window a set size...
primaryStage.setResizable(false);
// Create menu vbox and set the background image
VBox menuVBox = new VBox(30);
menuVBox.setBackground(new Background(new BackgroundImage(new
Image("image/bambooBG.jpg"), null, null, null, new BackgroundSize(45,
45, true, true, true, true))));
// Create start button
Button startButton = new Button("Start Game");
// TODO Some things...
// Need assistance here
// Create help button
Button helpButton = new Button("Help");
helpButton.setOnAction(e -> THINGS);
// Create music toggle button
ToggleButton musicButton = new ToggleButton("Music On/Off");
musicButton.setOnAction(e -> THINGS);
// Create credits button
Button creditsButton = new Button("Credits");
creditsButton.setOnAction(THINGS);
// Create exit button and set it to close the program when clicked
Button endButton = new Button("Exit Game");
endButton.setOnAction(e -> Platform.exit());
// Add all nodes to the vbox pane and center it all
// Must be in order from top to bottom
menuVBox.getChildren().addAll(startButton, helpButton, musicButton, creditsButton, endButton);
menuVBox.setAlignment(Pos.CENTER);
// New scene, place pane in it
Scene scene = new Scene(menuVBox, 630, 730);
// Place scene in stage
primaryStage.setTitle("-tiles-");
primaryStage.setScene(scene);
primaryStage.show();
}
// Needed to run JavaFX w/o the use of the command line
public static void main(String[] args) {
launch(args);
}
}
Restating: I want to click the Start button and have the currently open window change to an empty scene.
Here is a pastebin of the MenuFX class in its entirety:
http://pastebin.com/n6XbQfhc
Thank you for any help,
Bagger
The basic idea here is you would do something like:
public class GameFX {
private final BorderPane rootPane ; // or any other kind of pane, or Group...
public GameFX() {
rootPane = new BorderPane();
// build UI, register event handlers, etc etc
}
public Pane getRootPane() {
return rootPane ;
}
// other methods you may need to access, etc...
}
Now back in the MenuFX class you would do
Button startButton = new Button("Start Game");
startButton.setOnAction(e -> {
GameFX game = new GameFX();
primaryStage.getScene().setRoot(game.getRootPane());
});
How to make a button stacked behind a Label clickable?
Button
Button btn = new Button();
//TODO: button's main function, like onPressed, onReleased etc. here...
Custom label
CustomLabel sp = new CustomLabel("Some texts here"));
//TODO: custom label's main function, like a translucent background etc here...
//main purpose of this is to overlay the button
Main Pane
StackPane mainPane = new StackPane();
mainPane.getChildren.addAll(btn, sp);
With this, the area which the custom label overlays becomes unclickable.
Is there anyway to make the button still clickable even though overlay-ed, for example?
Or is there another way to do it? Something like setting label to not visible on click?
EDIT : To answer Itamar Green 's question..
By using the example as shown in this link: Mouse Events get Ignored on the Underlying Layer , it still does not seems to work. The button stacked under the layer is still not clickable.
sp.setPickOnBounds(false);
You can set the mouseTransparent property of the element(s) drawn on top to true. Note that this way all descendants of the node are ignored for mouse events:
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
System.out.println("Hello World!");
});
Region region = new Region();
region.setStyle("-fx-background-color: #0000ff88;");
region.setMouseTransparent(true);
StackPane root = new StackPane(btn, region);
Scene scene = new Scene(root, 100, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
Comment out
region.setMouseTransparent(true);
and the button will no longer react to mouse events in any way...
thanks for your help. I think I have solved my own question.
All I did was set a clickable event for my label.
Label sp = new Label("some texts here")
sp.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
//copy over the button's event.
}
});
Not sure if there is any better way of doing this...
in addition with the correct answer. you can enable or disable " mouse transparent " property via fxml with scenebuilder
I'm having difficulty finding out if this is even possible. The common behavior that most people want is to fade out an extension of a node, which is entirely possible through a FadeTransition
However, I'm trying to fade out an entire stage, so imagine closing the running program and instead of simply killing the windows (i.e. showing -> not showing), I would like the window (stage) to fade out over 2 seconds like a toast or notification would.
Create a timeline with a KeyFrame that changes the opacity of the stage's scene's root node. Also make sure to set the Stage style and the scene fill to transparent. Then make the program exit once the timeline is finished.
Below is an application with a single big button that, when clicked, will take 2 seconds to fade away, and then the program will close.
public class StageFadeExample extends Application {
#Override
public void start(Stage arg0) throws Exception {
Stage stage = new Stage();
stage.initStyle(StageStyle.TRANSPARENT); //Removes window decorations
Button close = new Button("Fade away");
close.setOnAction((actionEvent) -> {
Timeline timeline = new Timeline();
KeyFrame key = new KeyFrame(Duration.millis(2000),
new KeyValue (stage.getScene().getRoot().opacityProperty(), 0));
timeline.getKeyFrames().add(key);
timeline.setOnFinished((ae) -> System.exit(1));
timeline.play();
});
Scene scene = new Scene(close, 300, 300);
scene.setFill(Color.TRANSPARENT); //Makes scene background transparent
stage.setScene(scene);
stage.show();
}
public static void main (String[] args) {
launch();
}
}
i have a question about using virtual keyboard on touch supported pc with Windows 8.1. I have managed to show the virtual keyboard when textfield is focused with java switch:
-Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx
I found how to that on JavaFX Virtual Keyboard doesn't show1.
But when the keyboard show's up, it overlapps nodes below the keyboard.
According to what I read, http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/embed.htm, it should't be working like that.
Does anyone have any experience with that kind of problem?
When i run the test application it shows in full screen and embedded virtual keyboard is showing, becasue the textfield has focus. The textfield in this case is not visible until i "hide" the keyboard. I am not sure that this is the right approach so i need help please.
java -Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx application.TestVKB
public class TestVKB extends Application{
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) throws Exception {
TextField tfComment = new TextField();
tfComment.setPromptText("Enter comment");
BorderPane borderPane = new BorderPane();
borderPane.setBottom(tfComment);
Scene scene = new Scene(borderPane);
stage.setScene(scene);
stage.setMaximized(true);
stage.show();
}
}
After click in field username or password
I would be grateful for any advice. Thanks in advance.
As I've already pointed out in my first answer, the virtual keyboard is embedded in a PopupWindow, created in a different stage, and displayed on top of your current stage.
The option -Dcom.sun.javafx.vk.adjustwindow=true works, moving the main stage so the control is visible and there is no overlapping.
But when this input control is located at the bottom of the main stage, this is moved up to the center of the screen leaving a big empty gap that shows whatever is behind.
This second answer gives a solution to move the main stage just the required distance, without any gap, also taking into account the fade in/out animations of the virtual keyboard.
For starters, in our scene, we add a Button on the center, and the TextField on the bottom. With two controls we can change the focus easily and show/hide the keyboard.
To maximize the stage I'll use getVisualBounds(), so the taskbar can be visible.
private PopupWindow keyboard;
private final Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
private final Rectangle2D bounds = Screen.getPrimary().getBounds();
private final double taskbarHeight=bounds.getHeight()-visualBounds.getHeight();
#Override
public void start(Stage stage) {
TextField tfComment = new TextField();
tfComment.setPromptText("Enter comment");
BorderPane borderPane = new BorderPane(new Button("Click"));
borderPane.setBottom(tfComment);
Scene scene = new Scene(borderPane);
stage.setScene(scene);
stage.setX(visualBounds.getMinX());
stage.setY(visualBounds.getMinY());
stage.setWidth(visualBounds.getWidth());
stage.setHeight(visualBounds.getHeight());
stage.show();
}
We need to find the new stage when it's shown. In the same way as Scenic View, we'll use a deprecated method to get a valid window:
private PopupWindow getPopupWindow() {
#SuppressWarnings("deprecation")
final Iterator<Window> windows = Window.impl_getWindows();
while (windows.hasNext()) {
final Window window = windows.next();
if (window instanceof PopupWindow) {
if(window.getScene()!=null && window.getScene().getRoot()!=null){
Parent root = window.getScene().getRoot();
if(root.getChildrenUnmodifiable().size()>0){
Node popup = root.getChildrenUnmodifiable().get(0);
if(popup.lookup(".fxvk")!=null){
return (PopupWindow)window;
}
}
}
return null;
}
}
return null;
}
We'll call this method when the textfield gets the focus:
...
stage.show();
tfComment.focusedProperty().addListener((ob,b,b1)->{
if(keyboard==null){
keyboard=getPopupWindow();
}
});
}
Once we have the window, we can listen to changes in its position and move the main stage accordingly:
....
stage.show();
//findWindowExecutor.execute(new WindowTask());
tfComment.focusedProperty().addListener((ob,b,b1)->{
if(keyboard==null){
keyboard=getPopupWindow();
keyboard.yProperty().addListener(obs->{
System.out.println("wi "+keyboard.getY());
Platform.runLater(()->{
double y = bounds.getHeight()-taskbarHeight-keyboard.getY();
stage.setY(y>0?-y:0);
});
});
}
});
}
Note that instead of moving up the stage, another option will be resizing it (if there is enough space within the controls).
This will be the case where the textfield gets the focus and the virtual keyboard is fully shown:
Basically, the virtual keyboard is embedded in a PopupWindow, created in a different stage, and displayed on top of your current stage, at the bottom of the screen, no matter where the InputControl that triggers the keyboard is located.
You can see that on the FXVKSkin class:
winY.set(screenBounds.getHeight() - VK_HEIGHT);
But, just inmediately after that, you can find this:
if (vkAdjustWindow) {
adjustWindowPosition(attachedNode);
}
So, there's another command line option that you can use to move the stage so the node (the textfield in this case) will be on the center of the screen and you can type without overlapping it:
-Dcom.sun.javafx.vk.adjustwindow=true
Note that when the textfield loses the focus, the keyboard is hidden and the stage is moved again to its original position:
restoreWindowPosition(oldNode);
I've tested this option successfully, but when you have the textfield at the bottom of the screen, this will move your stage bottom to the center of the screen, leaving a big gap between both stages (you'll see whatever you have on the background).
I've managed to add a listener to the new stage and adjust the position just the necessary. If you are interested I could post it.
EDIT
Note this command line option won't work if the stage is maximized. A simple solution for this is:
Rectangle2D bounds = Screen.getPrimary().getBounds();
stage.setX(bounds.getMinX());
stage.setY(bounds.getMinY());
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.show();
I liked the solution, but in my case I prefer to move the keyboard using the showed method getPopupWindow i created a listener on textfield and changed the position of the keyboard directly.
textField.focusedProperty().addListener((ob, b, b1) -> {
if (keyboard == null) {
keyboard = getPopupWindow();
keyboard.setHideOnEscape(Boolean.TRUE);
keyboard.setAutoHide(Boolean.TRUE);
keyboard.centerOnScreen();
keyboard.requestFocus();
keyboard.sizeToScene();
}
Platform.runLater(() -> {
keyboard.setY(**NEW_POSITION_OF_KEYBOARD**);
});
});