Using FontAwesomeFX, how to have two icons for one button? - javafx

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>

Related

Random characters instead of String input in Combobox Items?

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

How to make Label take same height as font size in JavaFX?

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>

Retrieving strings from textfields in a .fxml file when a button is clicked. (creating a login scene to switch scenes to home scene)

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.

Reuse the same FXML declaration for menu bar and context menu

I have declared a menu bar in FXML with a bunch menu items (containing graphics, onClick method links etc...).
Now I'm creating a context menu for a table, and I'd like to put in there all the menu items for the "Edit" menu of the menu bar.
Is there a DRY way of doing so in FXML?
I don't like the idea of copying all the FXML declarations of the menu items, and having to maintain both sets of items.
I know I could reuse the items if I declared them in Java code, but I'd like to keep all my layout in FXML.
Here is the FXML for the edit menu, that I don't want to duplicate:
<Menu text="_Edit">
<MenuItem onAction="#copyRaw" text="Copy _raw log">
<accelerator>
<KeyCodeCombination alt="UP" code="C" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
<graphic>
<Glyph fontFamily="FontAwesome" icon="copy" />
</graphic>
</MenuItem>
<MenuItem onAction="#copyPretty" text="Copy with _columns">
<accelerator>
<KeyCodeCombination alt="UP" code="C" control="DOWN" meta="UP" shift="DOWN" shortcut="UP" />
</accelerator>
<graphic>
<Glyph fontFamily="FontAwesome" icon="copy" />
</graphic>
</MenuItem>
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem onAction="#selectAll" text="Select _All">
<accelerator>
<KeyCodeCombination alt="UP" code="A" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
<MenuItem mnemonicParsing="false" onAction="#unselectAll" text="Unselect All" />
</Menu>
I'm not sure that my idea is best but u should to do it like this:
You can create a package in resources with most used elements as Buttons,Tables,Labels etc. for each assign an fx:id and include that in another fxmls.
Example:
PACKAGE: resource/package/name/utils/Label.fxml
<?import javafx.scene.control.Label?>
<?import javafx.geometry.Insets?>
<Label xmlns:fx="http://javafx.com/fxml"
fx:id="label"
style="-fx-background-color: red;
-fx-font: bold;
-fx-font-size: 30px;"
text="Hello world">
<padding>
<Insets top="5" left="5" right="5" bottom="5"/>
</padding>
</Label>
<!--Add all your nodes there-->
PACKAGE: resource/package/name/Main.fxml
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="TOP_CENTER" hgap="10" vgap="10">
<fx:include source="Label.fxml"/> <!--There will be displayed all elements from Label.fxml-->
</GridPane>
In your case you just need to set fx:id for your Menu item and import in another fxml.
Good luck.

Text selection issue with embedded JavaFX into SWT

I am having a problem with my JavaFX TextArea. I use the FXCanvas to embed an few JavaFX controls into an SWT composite. Everything works fine except for the TextArea which doesn't allow me to highlight text by dragging. Double click and "right click"/"select all" work fine, so text selection does work.
My objects are defined in an FXML file, you cannot do anything simpler:
<Accordion fx:id="accordion" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.kratos.birt.report.data.oda.kairosdb.ui.FXMLController">
<panes>
<TitledPane fx:id="builderPane" text="Query Builder">
...
</TitledPane>
<TitledPane fx:id="jsonPane" text="Raw Query">
<content>
<VBox>
<children>
<Label text="Enter your query:">
<VBox.margin>
<Insets bottom="5.0" />
</VBox.margin>
</Label>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
<children>
<TextArea fx:id="queryArea" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</children>
</VBox>
</content>
</TitledPane>
</panes>
</Accordion>
I don't do any modification on it in the code, except for setting some text. The dragging selection doesn't work either if the TextArea isn't in the Accordion container.
The solution I found was to downgrade the version of the JRE (and thus the version of JavaFX) from 8 to 7.

Resources