I am trying to create a choicebox in my application using javafx/scenebuilder in IntelliJ but so far am not able to get Strings to show as menu items - in the example screenshot below I have just tried to create an option with the letter C? The code I have used is below. Any ideas what I am doing wrong? I thought it might be a font issue but I can't find a way to change the font of the menu items.
<AnchorPane prefHeight="45.0" prefWidth="127.5">
<children>
<Text fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="I" AnchorPane.leftAnchor="11.0" AnchorPane.topAnchor="4.0">
<font>
<Font name="Courier Bold" size="40.0" />
</font>
</Text>
<ChoiceBox fx:id="keyChoice" prefWidth="79.0" style="-fx-background-color: #FBC5B8;" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="8.0">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="C" />
</FXCollections>
</items>
</ChoiceBox>
</children>
</AnchorPane>
So this was a font issue as suspected, couldn't find a way to change it in FXML so created a CSS file which works fine.
.choice-box .menu-item .label {
-fx-font-family: "monospace";
}
.choice-box {
-fx-font-family: "monospace";
}
Related
I set the font size of upper label to 24px.
I don't know where I can check the real height of element (if it's possible in the Scene builder), but there is the extra space in upper (designated in the image) and lower part of box.
The line spacing is 0.
The parent VBox has no top padding.
All label sizes are computed.
I need the height of label equals to font size.
I mean FontSize = Gray space surrounded by blue markers height.
How to reach it?
I have faced with similar problem HTML/CSS.
There, not simple but working solution for most cases is negative margins and :before and :after pseudo elements.
Now which solutions are exists for JavaFX?
The repro
🌎 Repository
Open the resources/static/TasksOverview.fxml by Scene Builder.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="640.0" prefWidth="320.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox alignment="CENTER_LEFT">
<children>
<CheckBox mnemonicParsing="false" />
<VBox>
<children>
<Label style="-fx-font-size: 24px;" text="Wake up">
<VBox.margin>
<Insets />
</VBox.margin>
</Label>
<Label style="-fx-font-size: 14px;" text="... and fly. I need more text to test multiline mode." wrapText="true" />
</children>
<HBox.margin>
<Insets left="12.0" />
</HBox.margin>
</VBox>
</children>
<padding>
<Insets left="12.0" right="12.0" />
</padding>
</HBox>
<HBox alignment="CENTER_LEFT" layoutX="10.0" layoutY="10.0">
<children>
<CheckBox mnemonicParsing="false" />
<VBox>
<children>
<Label style="-fx-font-size: 24px;" text="Wash face">
<VBox.margin>
<Insets />
</VBox.margin>
</Label>
<Label style="-fx-font-size: 14px;" text="... with cold water." wrapText="true" />
</children>
<HBox.margin>
<Insets left="12.0" />
</HBox.margin>
</VBox>
</children>
<padding>
<Insets left="12.0" right="12.0" />
</padding>
</HBox>
</children>
</VBox>
Labels are "smart" controls that include, within the "skin" code, stuff like some in-built padding, as well as various alignment and spacing options for text and graphics, and support for resizing by dynamically eliding text.
If you want some more control over how text layout happens, then you can use raw Text nodes instead of Labels and then do some of the additional layout yourself if needed. Of course you are going to lose a lot of in-built functionality that way (buyer beware...), but sometimes that might be what you want.
For example, a Text node with the following attributes:
A font size of 24.
No spacing on the top, left or right of the visual area of the text.
A margin spacing of 3 pixels below the visual area of the text when placed in a VBox.
can be defined in FXML as below:
<Text boundsType="VISUAL" text="Visual bounds != Logical bounds">
<font>
<Font size="24.0" />
</font>
<VBox.margin>
<Insets bottom="3.0" />
</VBox.margin>
</Text>
If you use this stuff on a lot of text, then you can set a lot of the values in a style sheet rather than FXML (which would be preferable). I won't describe how to do that here other than to say there is an undocumented -fx-bounds-type css attribute for text.
Sometimes rather than using a Text node, it might be better to just "hack" a Label similar to Matt's answer by using stuff like negative insets (that is usually my preferred option...).
Be careful, esoteric discussion follows, get ready to ignore it ;-)
A key part is setting the boundsType to VISUAL. By default the bounds of the text are usually a bit more than what you actually see, which eases alignment issues, because that means the bounds of the letter "a" and the letter "A" are the same. That kind of bounds is the default and is called LOGICAL bounds. VISUAL bounds makes the bounds of those two letters different, so "a"'s bounds is smaller than "A"'s bounds, which is what allows stuff to not take up any more space than it absolutely needs to.
For example, using Text with VISUAL bounds and instead of a Label, gets rid of two sets of the extra whitespace around the text which appears on your example screen shot. One set of whitespace is allocated by the Label control's internal layout algorithm, another set of whitespace is allocated for the LOGICAL bounds.
Setting bounds to VISUAL is possible within a label by applying an appropriate CSS stylesheet, but if you do that, then the label still won't shrink to fit just the VISUAL bounds because it seems to be coded to work based off of LOGICAL bounds, at least that is what some quick testing I tried seemed to show. So using VISUAL bounds in text in a label just seems to make it display incorrectly (which may even be classified as bug by some people). It might work if you set a graphic with Text inside the label, but if you do that, the label doesn't do much for you and may as well just use a Text node directly (unless you are using a control like a TitledPane which includes a Label in the title, in which case you must use a Label).
Just set add a Negative inset and it will shrink the space above your label for example:
<Insets top="-5.0"/>
Full FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="640.0" prefWidth="320.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox alignment="CENTER_LEFT">
<children>
<CheckBox mnemonicParsing="false" />
<VBox>
<children>
<Label style="-fx-font-size: 24px;" text="Wake up">
<VBox.margin>
<Insets top="-5.0"/>
</VBox.margin>
</Label>
<Label style="-fx-font-size: 14px;" text="... and fly. I need more text to test multiline mode." wrapText="true" />
</children>
<HBox.margin>
<Insets left="12.0" />
</HBox.margin>
</VBox>
</children>
<padding>
<Insets left="12.0" right="12.0" />
</padding>
</HBox>
<HBox alignment="CENTER_LEFT" layoutX="10.0" layoutY="10.0">
<children>
<CheckBox mnemonicParsing="false" />
<VBox>
<children>
<Label style="-fx-font-size: 24px;" text="Wash face">
<VBox.margin>
<Insets />
</VBox.margin>
</Label>
<Label style="-fx-font-size: 14px;" text="... with cold water." wrapText="true" />
</children>
<HBox.margin>
<Insets left="12.0" />
</HBox.margin>
</VBox>
</children>
<padding>
<Insets left="12.0" right="12.0" />
</padding>
</HBox>
</children>
</VBox>
very new to programming. I am learning java and javaFX.
I have tried to make a login scene and a home scene and currently have a "login" button that invokes a method in the controller -loginButton()- that switches between the two scenes. The part I am unsure on is how to set up this method to retrieve the strings from the username and password text/password fields.
I am not interested just yet in setting this up with a database. what I want to go for is something like this (rubbish login details for the purpose of example, I would never actually use login info this bad):
public void loginButton(javafx.event.ActionEvent actionEvent) throws IOException {
if(textFromLoginField=="admin"){
if(textFromPasswordField=="Password123"){
//run code to change scene
}
}
}
I know how to switch scene but I dont know how to get the login info (shown as textFromLoginField and textFromPasswordField in the example above.
How I am switching scenes
Node node=(Node) actionEvent.getSource();
Stage stage=(Stage) node.getScene().getWindow();
stage.setScene(new Scene(FXMLLoader.load(getClass().getResource("homeScene.fxml")),750,500));
stage.show();
My FXML text:
VBox maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="159.0" prefWidth="157.0" spacing="10.0" style="-fx-background-color: Black;" HBox.hgrow="NEVER">
<HBox.margin>
<Insets bottom="60.0" top="60.0" />
</HBox.margin>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label text="LOGIN:" textFill="WHITE" />
<TextField fx:id="loginTextField" promptText="Username" />
<PasswordField fx:id="passwordTextField" promptText="Password" />
<HBox alignment="TOP_RIGHT" prefHeight="21.0" prefWidth="137.0" spacing="10.0">
<children>
<Button mnemonicParsing="false" fx:id="loginbutton" onAction="#loginButton" style="-fx-background-color: Blue;" text="Login" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
<Button mnemonicParsing="false" fx:id="helpbutton" onAction="#helpButton" style="-fx-background-color: Orange;" text="Help" textAlignment="CENTER" textFill="WHITE">
<font>
<Font name="System Bold" size="12.0" />
</font>
</Button>
</children>
</HBox>
</children>
</VBox>
Any help greatly appreciated :)
-Also, if I have used any technical vocab incorrectly please let me know. I am new to this. thanks
"==" doesn't work with Strings. Use textFromLoginField.equals();. Check out the string functions.
In my JavaFX program I am using FontAwesomeFX to add icons to buttons, labels, etc.
The way how I style this is through the .fxml file:
<Button fx:id="btnGoToWeb"
onAction="#btnGoToWeb">
<tooltip>
<Tooltip text="Go to Web"/>
</tooltip>
<graphic>
<FontAwesomeIconView glyphName="GLOBE" size="1.6em"/>
</graphic>
</Button>
Producing this button:
I would like to know how I can add 2 icons to one button. I would like to have something like shown below (please note the image is modified to illustrate the desired output):
Per #Slaw comment.
<Button mnemonicParsing="false" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<graphic>
<HBox alignment="CENTER" spacing="5.0">
<children>
<FontAwesomeIconView />
<FontAwesomeIconView />
</children>
</HBox>
</graphic>
<tooltip>
<Tooltip text="Go to Web" />
</tooltip>
</Button>
I am looking for an elegant way of setting a padding to a TabPane, but without padding the tab bar:
<TabPane>
<padding>
<Insets top="10" bottom="10" right="10" left="10" />
</padding>
<Tab text="red">
<Rectangle fill="RED" width="200" height="200" />
</Tab>
<Tab text="blue">
<Rectangle fill="BLUE" width="200" height="200" />
</Tab>
</TabPane>
gives:
however,
<TabPane>
<Tab text="red">
<VBox>
<padding>
<Insets top="10" bottom="10" right="10" left="10" />
</padding>
<Rectangle fill="RED" width="200" height="200" />
</VBox>
</Tab>
<Tab text="blue">
<VBox>
<padding>
<Insets top="10" bottom="10" right="10" left="10" />
</padding>
<Rectangle fill="BLUE" width="200" height="200" />
</VBox>
</Tab>
</TabPane>
gives:
which is exactly what i want, however I want to simplify the FXML structure, mainly by refactoring the <padding> element so it's declared in one place (shorter and non-repeating code) and not in every tab of the pane.
So is there any way to achieve this? Or am I stuck with my repeated <padding> elements? I'd prefer an FXML solution, but if no way exists a Java one is OK.
In a word: no.
Each Tab of the TabPane accepts a Node for it's contentProperty. The content itself is not a Region and therefore cannot have Insets or padding applied to it. The TabPane itself does not contain a method that allows you to style the content of all the child Tabs at once.
You must first add a container of some sort to the Tab in order to apply padding. So the second method in your question is the simplest way to accomplish what you are trying to do.
A Workaround
While this cannot be done with FXML, you could use a Java loop to add the same padding to all of your Tab objects after loading the scene:
Insets insets = new Insets(10);
for (Tab tab : tabPane.getTabs()) {
((VBox) tab.getContent()).setPadding(insets);
}
This assumes, of course, that you use a VBox for the content of all your tabs.
EDIT: I updated the answer to use the CSS selectors from fabian's comment down below.
You can set padding for most JavaFX scene graph objects in a separate css file. You will need to link the css file to your FXML file which I will show below. The css file and the FXML file will need to be in the same directory, otherwise you will have to edit the value="..." tag.
style.css
.tab-pane > .tab-content-area > * {
-fx-padding: 10 10 10 10;
}
This sets padding to all the VBoxes that happen to be under a Tab somewhere (no matter how deep in the hierarchy)
main.fxml
<TabPane>
<Tab text="red">
<VBox>
<Rectangle fill="RED" width="200" height="200" />
</VBox>
</Tab>
<Tab text="blue">
<VBox>
<Rectangle fill="BLUE" width="200" height="200" />
</VBox>
</Tab>
<stylesheets>
<URL value="#style.css" />
</stylesheets>
</TabPane>
I have defined the combo Box in javaFX FXML file now i want to define it's function to get the value of Combo Box and use it in my code.
The FXML file is
<ComboBox fx:id="select_pc" promptText="Select PC">
<HBox.margin>
<Insets left="20.0" top="35.0" />
</HBox.margin>
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="ForkLift" />
<String fx:value="Gates" />
</FXCollections>
</items>
</ComboBox>
now can anybody tell me how to write a function to take the value of combo Box and use it in the String form