I've been trying for days and days now to get a BorderPane region go over another region...
The problem is as follow: My app is set in a BorderPane root, With:
A header in its TOP region
A menu in its LEFT region
The content, depending on the page, in it's CENTER
And an optional panel on its RIGHT region
That right region is the problem. It should appear/disappear when clicking on a "notification button" that is in the TOP region. So far so good. The thing is that the app doesn't use the RIGHT region, so I'm trying to make the RIGHT region that contains an AnchorPane go over the CENTER region. The normal state of the app is without the RIGHT region and I don't want to resize the whole app when opening the noitifications. Tried several things, such as:
When clicking the notification button, send the CENTER part toBack() and set the RIGHT width to the 300 wanted pixels
Sending the RIGHT region toFront()
Sending the whole BorderPane toFront()
None of them work, as they all either not show, or resize the center part which I don't want. I'd like the RIGHT to float above the CENTER region when the notification menu is showing.... Is there any way to do that? Or maybe another idea to trigger a container that would show above the CENTER part? Of course, I go design the panel in every CENTER pane and make it visible or not, but my app is about 15 different center windows so it would be really bad in terms of modifications...
I think you should not be trying to make the borderpane do this for you or you will end up with behavior you do not want like the center NOT resizing when the application is resized while the panel is visible.
Remember that JavaFX is really 3D. How about you try to wrap the BorderPane inside of an AnchorPane, GridPane or ScrollPane (whichever makes sense) instead of trying to get the right insert to do your thing. e.g. add an ScrollPane (your Slider) to the containing AnchorPane and bring that to the front and anchor it's top, right and bottom.
This should give you a right-aligned ScrollPane on top of your borderpane.
Then of course if you want it to be fancy with an animated slide you can try this out : https://gist.github.com/jewelsea/1437374
or this:
http://blog.physalix.com/javafx2-borderpane-which-slides-in-and-out-on-command/
Here is a very rough example to show the idea:
public class JavaFXApplication2 extends Application {
ScrollPane slider;
AnchorPane root;
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Slide in");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
root.getChildren().add(slider);
AnchorPane.setRightAnchor(slider, 0.);
AnchorPane.setTopAnchor(slider, 0.);
AnchorPane.setBottomAnchor(slider, 0.);
slider.toFront();
}
});
Label l = new Label();
l.setText("Test Label to Show inside content");
Label l2 = new Label();
l2.setText("Peek-a-Boo");
slider = new ScrollPane();
slider.setStyle("-fx-border-color: orangered;");
slider.setContent(l2);
root = new AnchorPane();
root.getChildren().add(btn);
root.getChildren().add(l);
AnchorPane.setRightAnchor(l, 0.);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Related
I am trying to put multiple textfields in a circle in JavaFX. I could add a field in the centre using StackPane as explained in the below-mentioned post but unable to add multiple textfields. I tried using different panes for that but it didn't work.
Added the code that doesn't work.I want to add two text fields at any place inside a circle. Using gridpane for it didn't work. Moreover, I want to create x number of circle dynamically at any place in a gridpane and add multiple text fields to the circle, is it possible to do that using JavaFX?
Hope I am able to explain the problem statement correctly. Any response is appreciated :)
#Override
public void start(Stage arg0) throws Exception {
arg0.setTitle("Text Boxes In circle");
arg0.setMaxWidth(500);
Circle circle = createCircle(); // This function is to form a circle.
Text text = new Text("42");
Text text1 = new Text("36");
text.setBoundsType(TextBoundsType.VISUAL);
text1.setBoundsType(TextBoundsType.VISUAL);
GridPane box = new GridPane();
// box.setConstraints(text, 2, 0); commented this out to check if it was not
// causing problem but still didn't work
// box.setConstraints(text1, 2, 1);
// box.setAlignment(Pos.CENTER); Even used this to center the gridPane didn't
// work either.
StackPane stack = new StackPane();
box.getChildren().addAll(text, text1);
stack.getChildren().addAll(box, circle);
Scene scene = new Scene(stack);
arg0.setScene(scene);
arg0.show();
}
public static void main(String[] args) {
launch(args);
}
private static Circle createCircle() {
final Circle circle = new Circle(100);
circle.setStroke(Color.FORESTGREEN);
circle.setStrokeWidth(10);
circle.setStrokeType(StrokeType.INSIDE);
circle.setFill(Color.AZURE);
return circle;
}
how to put a text into a circle object to display it from circle's center?
I'm currently developing an app. It's visual structure is the following:
Only one Stage.
Only one Scene which has an ApplicationContainer's (my own class which
is basically a StackPane with a BorderPane inside of it with a
MenuBar on top, and the current page in it's center).
Multiple ApplicationLayout's
The ApplicationLayout has a Header and a Footer (footer not implemented yet) and looks like this:
I've managed to implement fadeIn / fadeOut transitions between the pages by setting a StackPane as the BorderPane's center, adding the page to it, and on top of that, a white VBox. So before I make the page switch I work with FadeTransitions of this white VBox.
I had to do it this way because setOpacity() wouldn't change the textfields or button opacities for some reason.
Now I'm trying to do the exact same thing for the header. So I setted a StackPane to the top, and added to it the header and a on top of it a "header coverer" which supposedly should do the trick just as before (can't modify the opacity property of the title, arrow or description because of CSS overriding).
But this time it's not working, if I set the opacity of the header coverer to anything but 0, the stuff in the header doesn't show.
What I want to acomplish is to fadeOut / FadeIn the components of the header but not the orange HBox.
EDIT: Added a minimal example where this doesn't work for me
public class Main extends Application {
private Boolean buttonPressed = false;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
BorderPane appWindow = new BorderPane();
appWindow.setStyle("-fx-alignment: center; -fx-padding: 30 0 0 30");
appWindow.setBackground(new Background(new BackgroundFill(Color.PERU, null, null)));
GridPane loginContainer = new GridPane();
appWindow.setCenter(loginContainer);
TextField username = new TextField();
PasswordField password = new PasswordField();
Label userNameDesc = new Label("Username");
Label passwordDesc = new Label("Password");
Button logInBtn = new Button("Log In");
logInBtn.setTranslateX(100);
logInBtn.setTranslateY(20);
logInBtn.setOnAction(event -> {
if (!buttonPressed) {
appWindow.getCenter().setOpacity(30);
buttonPressed = true;
System.out.println("Opacity set to " + appWindow.getCenter().getOpacity());
}
else {
appWindow.getCenter().setOpacity(100);
buttonPressed = false;
System.out.println("Opacity set to " + appWindow.getCenter().getOpacity());
}
});
loginContainer.addColumn(0, userNameDesc, passwordDesc);
loginContainer.addColumn(1, username, password);
loginContainer.add(logInBtn, 1, 2);
Scene scene = new Scene(appWindow, 300, 250);
stage.setScene(scene);
stage.show();
}
}
Pressing the "Log In" button should affect the Gridpane and Gridpane childs visual opacity, but it doesn't. It just prints the correct opacity values.
According to the documentation:
Opacity is specified as a value between 0 and 1. Values less than 0 are treated as 0, values greater than 1 are treated as 1.
So setting the value to 30 or to 100 has no effect: both are treated as fully opaque (i.e. they are clamped at 1).
Replacing
appWindow.getCenter().setOpacity(30);
with
appWindow.getCenter().setOpacity(0.3);
will make the center content partially transparent.
I have
a primary stage which the user can configure to be in fullscreen mode
secondary stages (tool windows) which the user can open. These windows should be always on top the the primary stage (regardless of whether its in fullscreen mode or not).
The latter does not work, even if I use setAlwaysOnTop(true) for the secondary stages they will disappear behind the primary stage once the user clicks on the primary stage.
This only happens when the primary stage is in full screen mode, everything works fine if the primary stage is not in fullscreen mode.
How can I enable this concept of tools windows in front of a fullscreen stage? Example code:
public class Test extends Application {
#Override
public void start(Stage stage) {
VBox vbox = new VBox();
Scene scene = new Scene(vbox);
stage.setScene(scene);
Button button1 = new Button("New Tool Window");
button1.setOnAction((e) -> {
Stage toolStage = new Stage();
Scene toolScene = new Scene(new Label("Am I on top?"), 300, 250);
toolStage.setScene(toolScene);
toolStage.initOwner(stage);
toolStage.setAlwaysOnTop(true);
toolStage.show();
});
Button button2 = new Button("Close");
button2.setOnAction((e) -> System.exit(0));
vbox.getChildren().addAll(button1, button2);
stage.show();
stage.setFullScreen(true);
}
public static void main(String[] args) {
launch(args);
}
}
Update 8/20/2016: Confirmed as a bug: JDK-8164210
A way to bypass this limitation is to:
Deactivate fullscreen mode
Create a keyCombination for psuedo fullscreen
Set the stage style undecorated and not resizable
Se the screen to the size of the user screen and position it at 0,0.
It is easy to create your own border for minimizing and closing the program as shown here:
JavaFX Stage.setMaximized only works once on Mac OSX (10.9.5)
And here:
JavaFX 8 Taskbar Icon Listener
you need to set initmodality after set initowner
toolStage.initOwner(stage);
toolStage.initModality(Modality.APPLICATION_MODAL);
I want to align i.e Position CENTER an OK button of a DialogPane. I have tried the below code but its not working.
Dialog dialog = new Dialog();
DialogPane dialogPane = dialog.getDialogPane();
dialogPane.setStyle("-fx-background-color: #fff;");
// Set the button types.
ButtonType okButtonType = new ButtonType("Ok", ButtonBar.ButtonData.OK_DONE);
ButtonType cancelButtonType = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
dialog.getDialogPane().getButtonTypes().addAll(okButtonType, cancelButtonType);
dialogPane.lookupButton(cancelButtonType).setVisible(false);
// Testing
Button okButton = (Button) dialog.getDialogPane().lookupButton(okButtonType);
okButton.setAlignment(Pos.CENTER);
// End Testing
dialog.showAndWait();
Centering buttons in the ButtonBar of a Dialog is actually surprisingly difficult to achieve in a non-hacky way.
Below is the best solution I could come up with. It relies upon a dynamic CSS lookup of the HBox for the button container, to which it then adds a spacer region on the right to push the buttons to the left (the default ButtonSkin implementation already places an implicit spacer of the left which pushes the buttons to the right, which I determined using ScenicView). The combination of the left and right spacers end up aligning the buttons in the center. The solution also overrides the ButtonBar creation to stop the ButtonSkin internally reordering and performing additional layout of buttons, as, when it does that, you can't really reliably customize the layout yourself.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.Optional;
public class CenteredDialogButtons extends Application {
#Override
public void start(Stage stage) {
Button show = new Button("Show Dialog");
Dialog<ButtonType> dialog = new Dialog<>();
DialogPane dialogPane = new DialogPane() {
#Override
protected Node createButtonBar() {
ButtonBar buttonBar = (ButtonBar) super.createButtonBar();
buttonBar.setButtonOrder(ButtonBar.BUTTON_ORDER_NONE);
return buttonBar;
}
};
dialog.setDialogPane(dialogPane);
dialogPane.getButtonTypes().addAll(ButtonType.OK);
dialogPane.setContentText("Centered Button");
Region spacer = new Region();
ButtonBar.setButtonData(spacer, ButtonBar.ButtonData.BIG_GAP);
HBox.setHgrow(spacer, Priority.ALWAYS);
dialogPane.applyCss();
HBox hbox = (HBox) dialogPane.lookup(".container");
hbox.getChildren().add(spacer);
show.setOnAction(e -> {
Optional<ButtonType> result = dialog.showAndWait();
if (result.isPresent() && result.get() == ButtonType.OK) {
System.out.println("OK");
}
});
StackPane layout = new StackPane(
show
);
layout.setPadding(new Insets(50));
Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The reason I don't quite like this solution is that the dynamic CSS lookups kind of violate API encapsulation, as the CSS structure of the JavaFX scene graphs for controls such as button bars is not really part of their public API. However, I don't think it is really possible to get centered buttons in a ButtonBar using the existing public APIs for JavaFX 8 and a default ButtonBar skin.
An alternate approach would be to create a custom skin for the ButtonBar associated with the dialog, but that approach is quite difficult and I wouldn't recommend it for this task.
Basically, the takeaway from all this is, just leave the default button layout and order for dialogs whenever you can, rather than trying to customize the dialog button layout. If you do want to have completely customized layout to the level of things like button placement, then you may be better off just creating your own custom dialog class by subclassing Stage rather than basing your custom dialog implementation on the in-built dialog class.
Related, but slightly different information is in:
Enter Key Event Is Not Working On Dialog In Javafx?
I tried to center OK button in Alert and I am not sure if this is bug or feature (Java8) but it was possible to center single button by setting new one:
alert.getButtonTypes().set(0, new ButtonType("OK", ButtonBar.ButtonData.LEFT));
As long as there is only one button with ButtonData.LEFT, it is centered in the middle of button panel. Obviously this solution does not work for panel with multiple buttons, but it might help to position single OK button.
Add this method to your code and call it when you need to align the buttons in a Dialog or Alert:
private void centerButtons(DialogPane dialogPane) {
Region spacer = new Region();
ButtonBar.setButtonData(spacer, ButtonBar.ButtonData.BIG_GAP);
HBox.setHgrow(spacer, Priority.ALWAYS);
dialogPane.applyCss();
HBox hboxDialogPane = (HBox) dialogPane.lookup(".container");
hboxDialogPane.getChildren().add(spacer);
}
Call it in this way: centerButtons(dialog.getDialogPane);
It's a kind of hack, but you could just do something like this:
okButton.translateXProperty().bind(okButton.prefWidthProperty().divide(-2));
The DialogPane is horizontal centered, so subtracting the okButton's half width will do the trick.
But I think this is a really dirty solution ;-)
Based on #ManuelSeiche's answer, here is how to compute exact distance to the center:
#FXML private Dialog<ButtonType> dialog;
#FXML private ButtonType btClose;
#FXML
private void initialize()
{
dialog.setOnShown(event ->
{
Platform.runLater(() ->
{
Button btnClose = (Button) dialog.getDialogPane().lookupButton(btClose);
HBox hBox = (HBox) btnClose.getParent();
double translateAmount = hBox.getWidth() / 2.0 - btnClose.getWidth() / 2.0 - hBox.getPadding().getLeft();
btnClose.translateXProperty().set(-translateAmount);
});
});
}
i was searching in google for hours and i still cant find the right answer, so i have a last chance to come here and ask.
i'm making school year JAVA FX project. I'm using NetBeans.
I have a point that i can see on the application i have. The problem is: I would like to have a big map (background) and I need to be able to move with my view. For example move by 50 to the right (x).
I have Application where I use Stage, Scene, StackPane.
I heard something about Dimensions in Java, but i can't use it in javafx application. Is there something similar, what can I use in my Application?
Thank you very much.
What I think you are asking for is a Scene with a map (represented as an Image) in the background and controls layered on top of the map to allow interaction with the map at certain positions. Your question is a little unclear, so I'm not exactly sure if that is what you are asking.
If so, here is some sample code to implement that.
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
/** Constructs a scene with a pannable Map background. */
public class PannableView extends Application {
private Image backgroundImage;
#Override public void init() {
backgroundImage = new Image("https://www.narniaweb.com/wp-content/uploads/2009/08/NarniaMap.jpg");
}
#Override public void start(Stage stage) {
stage.setTitle("Drag the mouse to pan the map");
// construct the scene contents over a stacked background.
StackPane layout = new StackPane();
layout.getChildren().setAll(
new ImageView(backgroundImage),
createKillButton()
);
// wrap the scene contents in a pannable scroll pane.
ScrollPane scroll = createScrollPane(layout);
// show the scene.
Scene scene = new Scene(scroll);
stage.setScene(scene);
stage.show();
// bind the preferred size of the scroll area to the size of the scene.
scroll.prefWidthProperty().bind(scene.widthProperty());
scroll.prefHeightProperty().bind(scene.widthProperty());
// center the scroll contents.
scroll.setHvalue(scroll.getHmin() + (scroll.getHmax() - scroll.getHmin()) / 2);
scroll.setVvalue(scroll.getVmin() + (scroll.getVmax() - scroll.getVmin()) / 2);
}
/** #return a control to place on the scene. */
private Button createKillButton() {
final Button killButton = new Button("Kill the evil witch");
killButton.setStyle("-fx-base: firebrick;");
killButton.setTranslateX(65);
killButton.setTranslateY(-130);
killButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent t) {
killButton.setStyle("-fx-base: forestgreen;");
killButton.setText("Ding-Dong! The Witch is Dead");
}
});
return killButton;
}
/** #return a ScrollPane which scrolls the layout. */
private ScrollPane createScrollPane(Pane layout) {
ScrollPane scroll = new ScrollPane();
scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setPannable(true);
scroll.setPrefSize(800, 600);
scroll.setContent(layout);
return scroll;
}
public static void main(String[] args) { launch(args); }
}
For the example use the mouse (or probably touch commands or trackpad scroll gestures - though I haven't a touch screen or trackpad to test it) to drag the map around. Click on the button to "Kill the evil witch".
The solution works by:
Creating an ImageView to hold the background map.
Constructing the scene contents in a StackPane over the stacked background ImageView.
Wrapping the scene in a ScrollPane bound to the scene's size.
Setting properties on the ScrollPane to make it pannable.