I have some issue with switch scenes at JavaFX. I have the primary stage that I set to him the first scene with background number 1:
then I switch to the new scene and I get this screen:
how can I resize my new CSS to cover the all screen?
I tried to set the background into my new scene but as you see that result above
css of second background:
.grass{
-fx-background-image:url("/images/25474739-closeup-image-of-natural-
green-grass-soccer-field.jpg");
-fx-background-repeat:stretch,stretch;
-fx-background-size:cover;
-fx-background-position: center center;
}
css of first one:
.root {
-fx-background-image: url("/images/menu.jpg");
-fx-background-size:cover;
-fx-background-position: center center;
}
the function that i change the scenes:
public void switchMain(String string , AnchorPane container,String css) {
try {
FXMLLoader fxmlLoader = new FXMLLoader();
AnchorPane root =
fxmlLoader.load(getClass().getResource("GameScreen.fxml").openStream());
container.getChildren().setAll(root);
if(!css.equals("")) {
myStage.getScene().getStylesheets().add(getClass().getResource
("MazeDisplyGra
ss.css").toExternalForm());
}
} catch (IOException e){
}
I am not have any idea how to solve it. so please, if you get some good solution , share it with me : )
Related
I am using an JavaFX Alert with a text area on it.
The problem I have is that the text area does not use the full space of the Alert, as well as having white (borders).
My code:
TextArea area = new TextArea("");
area.setWrapText(true);
area.setEditable(false);
area.getStylesheets().add(getClass().getResource("/model/app.css").toExternalForm());
Alert alert = new Alert(AlertType.NONE);
alert.getDialogPane().setPrefWidth(750);
alert.getDialogPane().setPrefHeight(800);
alert.getDialogPane().setContent(area);
formatDialog(alert.getDialogPane());
alert.setTitle("Lizenz Info");
Window w = alert.getDialogPane().getScene().getWindow();
w.setOnCloseRequest(e -> {
alert.hide();
});
w.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.ESCAPE) {
w.hide();
}
}
});
alert.setResizable(true);
alert.showAndWait();
My corresponding css sheet:
.text-area .content {
-fx-background-color: #4c4c4c;
}
.text-area {
-fx-text-fill: #ff8800;
-fx-font-size: 15.0px;
}
.text-area .scroll-pane {
-fx-background-color: #4c4c4c;
}
.text-area .scroll-pane .viewport {
-fx-background-color: #4c4c4c;
}
.text-area .scroll-pane .content {
-fx-background-color: #4c4c4c;
}
.viewport and .content on .scrollpane did not have any effect whatsoever.
I want the white borders either to be gone, or have the same color as the background, also to use the full space of the dialog. Can someone help?
As #jewelsea suggested, I think Alert is not the right choice here. Your desired layout can be acheived by using Dialog (as in below code).
Dialog<String> dialog = new Dialog<>();
dialog.setTitle("Lizenz Info");
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK);
dialog.getDialogPane().setContent(area);
dialog.setResizable(true);
dialog.showAndWait();
Having said that, you can fix the existing issues as below:
Remove white space around text area: You can remove the white space by setting the padding of TextArea to 0. Include the below code in the css file.
.text-area{
-fx-padding:0px;
}
Changing the white space background : The .text-area and .content styleclasses are on same node. So instead of declaring with space between them
.text-area .content {
-fx-background-color: #4c4c4c;
}
you have to declare without the space between the styleclasses (in below code)
.text-area.content {
-fx-background-color: #4c4c4c;
}
Here is a similar example to Sai's but uses a standard stage.
It uses a UTILITY style, but you could use a different style if you prefer.
Basically, if you don't want the additional styling and functionality of the alerts and dialogs (and you don't seem to with at least the example you have given), then you can just use a standard stage to display your content rather than the dialog classes provided in the javafx.control package.
The alert.css file referenced in the example is the CSS from your question.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TextAreaUtility extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) {
Button showAlert = new Button("Show Alert");
showAlert.setOnAction(this::showAlert);
stage.setScene(new Scene(showAlert));
stage.show();
}
private void showAlert(ActionEvent e) {
TextArea textArea = new TextArea("");
textArea.setWrapText(true);
textArea.setEditable(false);
Scene scene = new Scene(textArea, 750, 800);
scene.getStylesheets().add(
TextAreaUtility.class.getResource(
"alert.css"
).toExternalForm()
);
Stage utility = new Stage(StageStyle.UTILITY);
utility.initOwner(((Button) e.getSource()).getScene().getWindow());
utility.initModality(Modality.APPLICATION_MODAL);
utility.setTitle("Alert Title");
utility.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.getCode() == KeyCode.ESCAPE) {
utility.hide();
}
});
utility.setResizable(true);
utility.setScene(scene);
utility.showAndWait();
}
}
Debugging nodes and styles info
If you want to see the nodes and style names in your scene graph and you aren't using a tool like ScenicView, a quick debug function is:
private void logChildren(Node n, int lvl) {
for (int i = 0; i < lvl; i++) {
System.out.print(" ");
}
System.out.println(n + ", " + n.getLayoutBounds());
if (n instanceof Parent) {
for (Node c: ((Parent) n).getChildrenUnmodifiable()) {
logChildren(c, lvl+1);
}
}
}
Which you can attach to run when the window is displayed:
w.setOnShown(se -> logChildren(alert.getDialogPane().getScene().getRoot(), 0));
When you run this on a standard dialog you will see quite a few nodes in the scene graph with attached styles that you can find defined in the modena.css file within the JavaFX SDK. You will also see that some of the bounding boxes for the layout that are not related to your text area have width and height.
Those dialog styles by default have padding attached to them, which is why you are seeing padding around your TextArea. The padding is not in the text area but the content regions containing it within the dialog. To get rid of it, you need to set the padding in your custom CSS to override the default. I don't have the CSS for that, it is difficult to create sometimes and overriding default padding is probably best avoided when possible.
I have multiple buttons in in my javafx appliaction with mnemonics.
When I press "Alt" the mnemonics appear in a dark color but I want them to be white.
What is the right css selector for this?
I tried:
.mnemonic-underline: {
-fx-stroke: white;
}
But after that the underlines are visible all the time.
This should work:
:show-mnemonics > .mnemonic-underline {
-fx-stroke: white;
}
Example program:
public class MnemonicStylingSSCCE extends Application {
#Override
public void start(Stage stage) {
// Init label
final Label mnemonic = new Label("_Mnemonic");
mnemonic.setMnemonicParsing(true);
// Init scene
final Scene scene = new Scene(mnemonic);
scene.getStylesheets().add(MnemonicStylingSSCCE.class.getResource("mnemonic.css").toExternalForm());
stage.setScene(scene);
// Request focus & show
stage.requestFocus();
stage.show();
}
}
Side note - the content of mnemonic.css is CSS shown above (but with the red color instead of white).
I have been having some issues with a project i am working on. I wish to load my fxml content into an existing anchorpane and display it when the "next" button is clicked, I also wish to have the "back" button to set the anchorpane to the previous fxml file.
The issue I am having is that I have it working only once. If next is clicked it shows the correct fxml content, however if back is pressed it operates correctly once, the second time the window displayed contains no content:
#FXML
AnchorPane scenePane, allContent;
#FXML
public void handleNextAction() {
try {
scenePane.getChildren().clear();
AnchorPane newvalscene = (AnchorPane) FXMLLoader.load(getClass().getResource("ProjectDetails.fxml"));
scenePane.getChildren().setAll(newvalscene.getChildren());
} catch (IOException ex) {
Logger.getLogger(NewProjectController.class.getName()).log(Level.SEVERE, null, ex);
}
}
#FXML
public void handleBackAction() {
try {
// allContent.getChildren().clear();
AnchorPane newvalscene = (AnchorPane) FXMLLoader.load(getClass().getResource("newProjectWindow.fxml"));
allContent.getChildren().setAll(newvalscene.getChildren());
} catch (IOException ex) {
Logger.getLogger(NewProjectController.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have tried clearing the content of the anchorpanes however this just results in the anchorpane being empty with no content loaded from the FXML the second time the back button is pressed.
Note I tried debugging this but since there is no actual error its hard to trace and netbeans wont seem to show me the content of variables newvalscene which contains all the nodes to be rendered, but a println shows that it does contain the Vbox and children i expect to be shown.
Any help would be appreciated.
why all these SIr is there a reason ?
scenePane.getChildren().clear();
scenePane.getChildren().setAll(newvalscene.getChildren());//why replace?
allContent.getChildren().setAll(newvalscene.getChildren());//why replace ?
please try this
if you really have this
AnchorPane scenePane, allContent;
and scenePane is your Parent or Root, you can nest your items like
scenePane.getCHildren().add(child);
so relating to your codes
AnchorPane nextvalscene,backvalscene;
public void handleNextAction() {
try {
//scenePane.getChildren().clear(); remove this
if(nextvalscene == null){
nextvalscene = (AnchorPane) FXMLLoader.load(getClass().getResource("ProjectDetails.fxml"));
scenePane.getChildren().add(newvalscene);//change setAll to add and use the child itself
AnchorPane.setLeftNode(newvalscene, 0.0);//set constraint for your newvalscene AnchorPane
//do that for the rest esp top
}
nextvalscene.toFront();
} catch (IOException ex) {
Logger.getLogger(NewProjectController.class.getName()).log(Level.SEVERE, null, ex);
}
}
do same for handleBackAction
Logic is your parent or root scene is AnchorPane it can contain children, so no need to replace all its children, you can have them all inside by obscured by constraints on layout parameters, and change its re-ordering.
unless you have a reason to copying your Anchorpane's children to your scene children list, i think i missed
hope it helps
I'm trying to make a card like the bootstrap CSS, but using JavaFX components. I want a rounded border but the background color of the top part (the header) is giving me problems.
The background overflows the border and looks quite ugly. I've googled a bit and found that an overflow:hidden on the background color should solve it. JavaFX css doesn't seem to have that though. Is there another way of solving this?
My solution so far:
As described in the JavaFX CSS Reference Guide, overflow is not supported.
JavaFX CSS does not support CSS layout properties such as float, position, overflow, and width. However, the CSS padding and margins properties are supported on some JavaFX scene graph objects. All other aspects of layout are handled programmatically in JavaFX code. In addition, CSS support for HTML-specific elements such as Tables are not supported since there is no equivalent construct in JavaFX.
However, to solve the rounded-background issue you can use -fx-background-radius along with -fx-border-radius. They should be the same value. You can find it here in the reference guide.
Here's an example of a bootstrap-like card that I think you are trying to make. You would use -fx-background-radius: <top-left> <top-right> <bottom-right> <bottom-left>; which would be -fx-background-radius: 10 10 0 0;
public class Card extends StackPane {
public BorderPane border = new BorderPane();
public StackPane header = new StackPane(), content = new StackPane();
public Card() {
setAlignment(Pos.CENTER);
getChildren().add(border);
border.setTop(header);
border.setCenter(content);
border.setStyle("-fx-border-color: cornflowerblue; -fx-border-radius: 10; ");
header.setStyle("-fx-background-color: derive(cornflowerblue, 70%); -fx-background-radius: 10 10 0 0; ");
header.setMinWidth(100);
header.setMinHeight(80);
content.setMinWidth(100);
content.setMinHeight(100);
}
public BorderPane getCard() {
return border;
}
public StackPane getHeader() {
return header;
}
public StackPane getContent() {
return content;
}
}
public void start(Stage stage) throws Exception {
Card card = new Card();
card.setPadding(new Insets(10,10,10,10));
GridPane grid = new GridPane();
grid.setVgap(10); grid.setHgap(10);
grid.setAlignment(Pos.CENTER);
grid.addRow(0, new Label("Username"), new TextField());
grid.addRow(1, new Label("Password"), new PasswordField());
grid.addRow(2, new Button("Submit"));
card.getContent().getChildren().add(grid);
Label title = new Label("Card Example");
title.setFont(Font.font("Tahoma", FontWeight.SEMI_BOLD, 36));
card.getHeader().getChildren().add(title);
StackPane stack = new StackPane();
stack.setAlignment(Pos.CENTER);
stack.getChildren().add(card);
Scene scene = new Scene(stack, 500, 300);
stage.setTitle("Boostrap-like Card Example");
stage.setScene(scene);
stage.show();
}
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.