Set different size of button text lines, css, javafx - css

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;
}

Related

Setting an imageview as an icon on a button

I was trying to write a JavaFX application; I wanted to put images in my icons and make them transparent, so that you would click on the ImageView without seeing the button.
Here i have the scenebuilder were i got the imageview and in the button in style i said: -fx-background-color transparent
Then we have here the preview of what is going to show
And lastly, this is the application when i run it on netbeans
i wanted to put images in my icons and make them transparent so you clicked on the imageview and you didn't saw the button.
Just call btn.setBackground(Background.EMPTY); to remove the default background of the button.
eg:
#Override
public void start(Stage primaryStage) {
ImageView iv = new ImageView("https://image.flaticon.com/icons/png/512/33/33949.png");
iv.setPreserveRatio(true);
iv.setFitWidth(60);
Button btn = new Button("", iv);
btn.setBackground(Background.EMPTY);
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
Produces:

Javafx Button size, EmptyBorder, and Read txt File into TextArea

I am trying to switch to javafx instead of swing but it has been a bit bumpy trying to find methods that do the exact tasks.
I am trying to get the buttons width to fill the entire scene and adjusts accordingly when you adjust the scene size.
Get a small empty border around text area and buttons.
Getting a method that reads a plain text file and replaces the current Text Area (not append).
package gui;
mport javafx.application.Application;
mport javafx.scene.Scene;
mport javafx.scene.control.Button;
mport javafx.stage.Stage;
mport javafx.scene.layout.*;
mport javafx.scene.control.TextArea;
public class Main extends Application{
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("TextArea Experiment 1");
TextArea textArea = new TextArea();
// Which TextArea method would I call to set a plain
// text file into the text area ?
BorderPane border = new BorderPane();
border.setCenter(textArea);
//border.setBorder(new EmptyBorder(10,10,10,10));
// Is there a method like this in JavaFx ?
GridPane grid = new GridPane();
border.setBottom(grid);
double screensize = border.getMaxWidth();
Button option1 = new Button("Button 1");
Button option2 = new Button("Button 2");
Button option3 = new Button("Button 3");
// how can I get the buttons to be max scene size and
//adjust dynamically to scene dimensions ?
option1.setMaxSize(Double.MAX_VALUE,Double.MAX_VALUE);
//option1.setPrefWidth(Double.MAX_VALUE);
System.out.println(screensize);
grid.add(option1, 0,1);
grid.add(option2,0,2);
grid.add(option3,0,3);
Scene scene = new Scene(border, 200, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
first of all I suggest that to take a look at this tutorial: http://code.makery.ch/library/javafx-8-tutorial/
If you want to build a well structured javafx application you have to make an .fxml file, a Controller class and (some) model class(es).
But for those points here are the answers.
If you want to set a Region's size you have to use .setPrefSize(double,double) method, if you want to set dynamic you have to use for example myButton.prefSizeProperty().bind(anyRegionYouWantToBindTo.widthProprty())
I don't really understand what you want, I think you would like to use some styling, then you can write a .css file then arr it to textArea's styleClass.
After you get the text from the file instead of using textArea.appendText(String) you have to user textArea.setText(String)
I think these are the sollutions for your problems but I strongly recommend to read a tutorial about javafx. So have fun :)
Rewrite your question and only ask the question for this answer. You can then ask the other questions on their own thread.
GridPane grid = new GridPane();
grid.setMaxWidth(Double.MAX_VALUE);//Make sure the GridPane MaxWidth is set to MAX_VALUE. you can use grid.gridLinesVisibleProperty().set(true); to get an idea of the GRIDPANES current borders
border.setBottom(grid);
grid.gridLinesVisibleProperty().set(true);
Button option1 = new Button("Button 1");
option1.setMaxWidth(Double.MAX_VALUE);//Set button one MaxWidth to MAX_VALUE
Button option2 = new Button("Button 2");
option2.setMaxWidth(Double.MAX_VALUE);//Set button two MaxWidth to MAX_VALUE
Button option3 = new Button("Button 3");
option3.setMaxWidth(Double.MAX_VALUE);//Set button three MaxWidth to MAX_VALUE
//Add ColumnConstraints and set the width to 100%.
ColumnConstraints columnConstraint = new ColumnConstraints();
columnConstraint.setPercentWidth(100);
grid.getColumnConstraints().add(0, columnConstraint);
grid.add(option1, 0, 1);
grid.add(option2, 0, 2);
grid.add(option3, 0, 3);

does JavaFX css have a way to stop background color getting over the border edges?

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();
}

JavaFX. How to make the border of imageview, when I click the imageview?

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;
}

JavaFX Right Coordinate of a CustomMenuItem

I have a Class that extends the CustomMenuItem. This MenuItems are added to a ContextMenu. Now i need to get the X-Coordinates from the right side of the CustomMenuItem.
The Problem is, that I have no idea how I can get the Coordinates.
The CustMenuItem has no function for getting the Coordinates like getX() or getY().
So how can I solve this problem?
This thing I would like to get:
Here we can see a Sample for a Context Menu (red lines). In the Context Menu are a lot of different CustomMenuItems implemented. Now I would like to get the right top corner Coordinate of the CustomMenuItem.
Thank you for your very nice help.
Before dealing with menu items, let's start saying that a ContextMenu is a popup window, so it has Windowproperties. You can ask for (x,y) left, top origin, and for (w,h).
But you have to take into account the effects, since by default it includes a dropshadow. And when it does, there's an extra space added of 24x24 pixels to the right and bottom.
.context-menu {
-fx-effect: dropshadow( gaussian , rgba(0,0,0,0.2) , 12, 0.0 , 0 , 8 );
}
Since this default dropshadow has a radius of 12px, and Y-offset to the bottom of 8px, the right and bottom coordinates of the context menu, including the 24x24 area, are given by:
X=t.getX()+cm.getWidth()-12-24;
Y=t.getY()+cm.getHeight()-(12-8)-24;
where t could be a MouseEvent relative to the scene, and values are hardcoded for simplicity.
Let's see this over an example. Since you don't say how your custom menu items are implemented, I'll just create a simple Menu Item with graphic and text:
private final Label labX = new Label("X: ");
private final Label labY = new Label("Y: ");
#Override
public void start(Stage primaryStage) {
final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = createMenuItem("mNext", "Next Long Option",t->System.out.println("next"));
MenuItem cmItem2 = createMenuItem("mBack", "Go Back", t->System.out.println("back"));
SeparatorMenuItem sm = new SeparatorMenuItem();
cm.getItems().addAll(cmItem1,cmItem2);
VBox root = new VBox(10,labX,labY);
Scene scene = new Scene(root, 300, 250);
scene.setOnMouseClicked(t->{
if(t.getButton()==MouseButton.SECONDARY || t.isControlDown()){
// t.getX,Y->scene based coordinates
cm.show(scene.getWindow(),t.getX()+scene.getWindow().getX()+scene.getX(),
t.getY()+scene.getWindow().getY()+scene.getY());
labX.setText("Right X: "+(t.getX()+cm.getWidth()-12-24));
labY.setText("Bottom Y: "+(t.getY()+cm.getHeight()-4-24));
}
});
scene.getStylesheets().add(getClass().getResource("root.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setTitle("Scene: "+scene.getWidth()+"x"+scene.getHeight());
}
private MenuItem createMenuItem(String symbol, String text, EventHandler<ActionEvent> t){
MenuItem m=new MenuItem(text);
StackPane g=new StackPane();
g.setPrefSize(24, 24);
g.setId(symbol);
m.setGraphic(g);
m.setOnAction(t);
return m;
}
If you remove the effect:
.context-menu {
-fx-effect: null;
}
then these coordinates are:
X=t.getX()+cm.getWidth();
Y=t.getY()+cm.getHeight();
Now that we have the window, let's go into the items.
MenuItem skin is derived from a (private) ContextMenuContent.MenuItemContainer class, which is a Region where the graphic and text are layed out.
When the context menu is built, all the items are wrapped in a VBox, and all are equally resized, as you can see if you set the border for the item:
.menu-item {
-fx-border-color: black;
-fx-border-width: 1;
}
This is how it looks like:
So the X coordinates of every item on the custom context menu are the same X from their parent (see above, with or without effect), minus 1 pixel of padding (by default).
Note that you could also go via private methods to get dimensions for the items:
ContextMenuContent cmc= (ContextMenuContent)cm.getSkin().getNode();
System.out.println("cmc: "+cmc.getItemsContainer().getBoundsInParent());
Though this is not recommended since private API can change in the future.
EDIT
By request, this is the same code removing lambdas and css.
private final Label labX = new Label("X: ");
private final Label labY = new Label("Y: ");
#Override
public void start(Stage primaryStage) {
final ContextMenu cm = new ContextMenu();
MenuItem cmItem1 = createMenuItem("mNext", "Next Long Option",action);
MenuItem cmItem2 = createMenuItem("mBack", "Go Back", action);
SeparatorMenuItem sm = new SeparatorMenuItem();
cm.getItems().addAll(cmItem1,cmItem2);
VBox root = new VBox(10,labX,labY);
Scene scene = new Scene(root, 300, 250);
scene.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if(t.getButton()==MouseButton.SECONDARY || t.isControlDown()){
// t.getX,Y->scene based coordinates
cm.show(scene.getWindow(),t.getX()+scene.getWindow().getX()+scene.getX(),
t.getY()+scene.getWindow().getY()+scene.getY());
labX.setText("Right X: "+(t.getX()+cm.getWidth()-12-24));
labY.setText("Bottom Y: "+(t.getY()+cm.getHeight()-4-24));
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setTitle("Scene: "+scene.getWidth()+"x"+scene.getHeight());
}
private MenuItem createMenuItem(String symbol, String text, EventHandler<ActionEvent> t){
MenuItem m=new MenuItem(text);
StackPane g=new StackPane();
g.setPrefSize(24, 24);
g.setId(symbol);
SVGPath svg = new SVGPath();
svg.setContent("M0,5H2L4,8L8,0H10L5,10H3Z");
m.setGraphic(svg);
m.setOnAction(t);
return m;
}
private final EventHandler<ActionEvent> action = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("action");
}
};

Resources