What JavaFX container should I use to create something like the colored boxes below?
Each colored box needs to hold two labels, the title of the box and the numeric result of the conversion.
Any suggestion is appreciated.
Here is an example of how to use VBoxes inside a FlowPane. Its obviously not exactly the same as your due to the fact that you did not post a Minimal, Reproducible Example but you get the idea.
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
FlowPane flowPane = new FlowPane();
flowPane.setStyle("-fx-background-color: rgb(50, 50, 50)");
flowPane.setOrientation(Orientation.VERTICAL);
flowPane.setVgap(20);
flowPane.getChildren().add(new TextField("1"));
VBox gramsVBox = new VBox();
gramsVBox.setStyle("-fx-background-color: Blue; -fx-background-radius: 5 5 5 5;");
gramsVBox.getChildren().add(new Label("Grams:"));
gramsVBox.getChildren().add(new Label("453.000000001"));
VBox kiloGramsVBox = new VBox();
kiloGramsVBox.setStyle("-fx-background-color: Green; -fx-background-radius: 5 5 5 5;");
kiloGramsVBox.getChildren().add(new Label("KiloGrams:"));
kiloGramsVBox.getChildren().add(new Label(".453000000001"));
VBox ouncesVBox = new VBox();
ouncesVBox.setStyle("-fx-background-color: Red; -fx-background-radius: 5 5 5 5;");
ouncesVBox.getChildren().add(new Label("Ounces"));
ouncesVBox.getChildren().add(new Label("16"));
flowPane.getChildren().addAll(gramsVBox,kiloGramsVBox,ouncesVBox);
Stage stage = new Stage();
stage.setHeight(220);
stage.setScene(new Scene(flowPane));
stage.show();
}
}
Related
So in windows 10 you have the windows menu with the icons on the left side:
When clicking on the hamburger icon the menu expands and text is show.
The expanded part is overlaying the content. The text is showing. and it was animated in (sliding transition).
In my application I want to make a similar menu on the right side (see blue part):
I have absolutely no idea how to get this effect. Currently I made a button with a graphic. I only display the graphic and when I click on the hamburger I show all the text by changing the setContentDisplay(ContentDisplay.GRAPHIC_ONLY) to setContentDisplay(ContentDisplay.RIGHT) 2 things that are wrong with this approach.
it pushes the content.
You cannot add a transition.
Any help would be appreciated, especially examples.
Demo
I made a demo that shows what I currently have:
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
JFXButton[] jfxButtons = {
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
};
JFXHamburger hamburger = new JFXHamburger();
HamburgerNextArrowBasicTransition transition = new HamburgerNextArrowBasicTransition(hamburger);
transition.setRate(-1);
hamburger.setAlignment(Pos.CENTER_RIGHT);
hamburger.setPadding(new Insets(5));
hamburger.setStyle("-fx-background-color: #fff;");
hamburger.setOnMouseClicked(event -> {
transition.setRate(transition.getRate() * -1);
transition.play();
if (transition.getRate() == -1) {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
} else {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.RIGHT);
}
}
});
ScrollPane scrollPane = new ScrollPane();
VBox vBox = new VBox();
scrollPane.setContent(vBox);
vBox.getStyleClass().add("content_scene_right");
vBox.getChildren().add(hamburger);
vBox.getChildren().addAll(jfxButtons);
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setMaxWidth(Double.MAX_VALUE);
jfxButton.setRipplerFill(Color.valueOf("#40E0D0"));
VBox.setVgrow(jfxButton, Priority.ALWAYS);
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
vBox.setFillWidth(true);
Label labelHoverOverTest = new Label("Testing label");
VBox vbox2 = new VBox();
vbox2.getChildren().addAll(labelHoverOverTest);
vbox2.setAlignment(Pos.CENTER_RIGHT);
root.setRight(scrollPane);
root.setCenter(vbox2);
Scene scene = new Scene(root);
primaryStage.setMinWidth(400);
primaryStage.setMinHeight(400);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I used JFoenix and fontawesomefx for this demo, but it can also be javafx scene buttons with any graphic.
Here are some images of what the demo looks like:
As you can see it pushes it the content in the center and I can't add any transition.
(here is a sample from bootstrap to give you an idea on What I'm trying to make it look like 1: https://bootsnipp.com/snippets/Pa9xl, 2: https://bootsnipp.com/snippets/featured/navigation-sidebar-with-toggle (with this one the content still moves, but it should give you a clear idea on what my vision is))
Problem is that you are using BorderPane and placing everything on same layer, so when content on right changes width it will affect one in the center and such.
In other to avoid this you should make it layered, so for root of view use StackPane, this pane should have 2 children, 1 for main content and 1 for sidebar, make sure that sidebar is above main content, now this 2 can be any Pane that you want. This way sidebar will be placed over main content and it won't push content.
Using code you provided and just adding StackPane you get something like this:
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
BorderPane mainContent = new BorderPane();
BorderPane sidebar = new BorderPane();
JFXButton[] jfxButtons = {
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),};
JFXHamburger hamburger = new JFXHamburger();
HamburgerNextArrowBasicTransition transition = new HamburgerNextArrowBasicTransition(hamburger);
transition.setRate(-1);
hamburger.setAlignment(Pos.CENTER_RIGHT);
hamburger.setPadding(new Insets(5));
hamburger.setStyle("-fx-background-color: #fff;");
hamburger.setOnMouseClicked(event -> {
transition.setRate(transition.getRate() * -1);
transition.play();
if (transition.getRate() == -1) {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
} else {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.RIGHT);
}
}
});
ScrollPane scrollPane = new ScrollPane();
VBox vBox = new VBox();
scrollPane.setContent(vBox);
vBox.getStyleClass().add("content_scene_right");
vBox.getChildren().add(hamburger);
vBox.getChildren().addAll(jfxButtons);
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setMaxWidth(Double.MAX_VALUE);
jfxButton.setRipplerFill(Color.valueOf("#40E0D0"));
VBox.setVgrow(jfxButton, Priority.ALWAYS);
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
vBox.setFillWidth(true);
Label labelHoverOverTest = new Label("Testing label");
VBox vbox2 = new VBox();
vbox2.getChildren().addAll(labelHoverOverTest);
vbox2.setAlignment(Pos.CENTER_RIGHT);
mainContent.setCenter(vbox2);
sidebar.setRight(scrollPane);
root.getChildren().addAll(mainContent, sidebar);
Scene scene = new Scene(root);
primaryStage.setMinWidth(400);
primaryStage.setMinHeight(400);
primaryStage.setScene(scene);
primaryStage.show();
}
As for transition I'm not sure what is problem there, for me it works fine.
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 made a button using scenebuilder which has two lines of text inside (first line is the function for button, and second one is a little explanation), and I would like to set different sizes for them, through css. Is this possible in any way, or is there more practical way for doing this?
Thank you for your help.
You cannot achieve this with a single text element like the one used for the button text, but you can add a Label as graphic and apply different text sizes via css:
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Text");
Label explanation = new Label("This is the explanation");
explanation.getStyleClass().add("explanation");
btn.setGraphic(explanation);
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 300);
scene.getStylesheets().add(getClass().getResource("explanation.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
explanation.css
.button {
-fx-font-size: 20;
-fx-content-display: bottom;
}
.button>.explanation {
-fx-font-size: 10;
}
For an editor that can map a Noise Function (-1 to 1 values) to Colors I need some Control that lets me define a Color Gradient, so something like
Value
- 0 is black
- 0.3 is yellow
- 0.8 is red
- 1 is white
so the whole gradient goes from black to white and thats editable,
is there anything like that built into JavaFX or do I have to write my own Control?
Basically smth like this:
Thanks in advance
Actually, Scene Builder has a powerful gradient editor that allows inserting multiple stops:
The control is called PaintPicker, and it is part of the Scene Builder Kit that you can download from here.
Once you have the jar, you can use the component.
This is a short snippet to show how to easily add it to your scene:
#Override
public void start(Stage primaryStage) {
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
PaintPickerController controller;
final FXMLLoader loader = new FXMLLoader();
loader.setLocation(PaintPicker.class.getResource("PaintPicker.fxml"));
try {
final VBox picker = loader.load();
controller = loader.getController();
controller.paintProperty().addListener((obs, ov, nv) -> System.out.println("Paint: " + nv));
root.getChildren().add(picker);
} catch (IOException ex) {
throw new IllegalStateException(ex);
}
Scene scene = new Scene(root, 320, 600);
primaryStage.setTitle("SceneBuilder PaintPicker");
primaryStage.setScene(scene);
primaryStage.show();
}
With the listener, you will get immediately the gradient:
Paint: linear-gradient(from 60.096% 38.461% to 47.115% 45.192%,
reflect, 0xda7777ff 0.0%, 0x226621ff 28.667%, 0xf2ff1cff 49.333%,
0xff1c5fff 73.0%, 0xffffffff 100.0%)
I think you are looking for a ColorPicker.
More information on how to use it is on JavaFX tutorials page.
In javaFX, I want make a imageview that can change border when I click.
When click once, then imageview has a border.
When click again, then imageview doesn't have a border.
How can I make that?
Thanks in advance!
Well you will need:
a PseudoClass for toggling the CSS state
a wrapping Region, because the ImageView itself does neither support a background nor a border.
A simple working example (the toggling of the PseudoClass is done with the help of a BooleanProperty, which is common practice and makes the management of its state easier):
#Override
public void start(Stage primaryStage) {
PseudoClass imageViewBorder = PseudoClass.getPseudoClass("border");
ImageView imageview = new ImageView(
new Image("http://upload.wikimedia.org/wikipedia/commons/1/16/Appearance_of_sky_for_weather_forecast,_Dhaka,_Bangladesh.JPG"));
BorderPane imageViewWrapper = new BorderPane(imageview);
imageViewWrapper.getStyleClass().add("image-view-wrapper");
BooleanProperty imageViewBorderActive = new SimpleBooleanProperty() {
#Override
protected void invalidated() {
imageViewWrapper.pseudoClassStateChanged(imageViewBorder, get());
}
};
imageview.setOnMouseClicked(ev -> imageViewBorderActive
.set(!imageViewBorderActive.get()));
BorderPane root = new BorderPane(imageViewWrapper);
root.setPadding(new Insets(15));
Scene scene = new Scene(root, 700, 400);
scene.getStylesheets().add(
getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
and the necessary CSS:
.image-view-wrapper:border {
-fx-border-color: black;
-fx-border-style: solid;
-fx-border-width: 5;
}