JavaFX Scene Builder, multiple ImageViews with the same image - performance

I have placed a few image views to the scene, all pointing to the same image with different
viewports.
generated fxml:
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fitHeight="150.0" fitWidth="200.0" layoutX="80.0" layoutY="91.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../../../../Pictures/sas.png" />
</image>
<viewport>
<Rectangle2D height="50.0" minY="50.0" width="50.0" />
</viewport>
</ImageView>
<ImageView fitHeight="150.0" fitWidth="200.0" layoutX="308.0" layoutY="91.0" pickOnBounds="true" preserveRatio="true">
<viewport>
<Rectangle2D height="50.0" minX="50.0" minY="50.0" width="50.0" />
</viewport>
<image>
<Image url="#../../../../../Pictures/sas.png" />
</image>
</ImageView>
<ImageView layoutX="225.0" layoutY="250.0">
<image>
<Image url="#../../../../../Pictures/sas.png" />
</image>
</ImageView>
</children>
Question is, will this create 3 instances of the same image in memory?
If yes, then what is the best ways to avoid it, url("") in style attribute, css class? I would like to avoid creating css class for each individual icon!
Is it even worth using single large croped image for multiple icons & UI elements instead of small image for each at this day & age?

A quick test shows that the ImageViews do not reference the same Image in memory.
To do so, you can either used css as you described, or you can define the Image once in the FXML with an <fx:define> block and reference it via its fx:id attribute:
<fx:define>
<Image url="#../../../../../Pictures/sas.png" fx:id="sasImage" />
</fx:define>
<ImageView image="$sasImage" fitHeight="150.0" fitWidth="200.0" layoutX="80.0" layoutY="91.0" pickOnBounds="true" preserveRatio="true">
<viewport>
<Rectangle2D height="50.0" minY="50.0" width="50.0" />
</viewport>
</ImageView>
<ImageView image="$sasImage" fitHeight="150.0" fitWidth="200.0" layoutX="308.0" layoutY="91.0" pickOnBounds="true" preserveRatio="true">
<viewport>
<Rectangle2D height="50.0" minX="50.0" minY="50.0" width="50.0" />
</viewport>
</ImageView>
<ImageView image="$sasImage" layoutX="225.0" layoutY="250.0">
</ImageView>

Related

View becomes invisible when I add attach custom view background to the view

I am trying to add a custom background to a button to make two sides rounded. But when I attach or add custom view background, the button becomes invisible. Here is my xml code:
<android.support.constraint.ConstraintLayout
Have Some Code there
<Button
android:id="#+id/Top"
android:layout_width="30dp"
android:layout_height="34dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:drawableTop="#drawable/baseline_remove_24"
android:elevation="5dp"
android:paddingTop="5dp"
android:translationZ="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="#+id/mid_button"
android:layout_width="30dp"
android:layout_height="23dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="#drawable/button_mid"
android:text="2"
app:layout_constraintBottom_toBottomOf="#+id/bottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/Top" />
<Button
android:id="#+id/bottom"
android:layout_width="30dp"
android:layout_height="34dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:background="#drawable/button_bottom_side"
//background added there
android:drawableBottom="#drawable/baseline_add_24"
android:elevation="5dp"
android:paddingBottom="5dp"
android:translationZ="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
</android.support.constraint.ConstraintLayout>
Code for custom view from drawable folder is here:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:topLeftRadius="0dp"
android:topRightRadius="0dp"
android:bottomLeftRadius="50dp"
android:bottomRightRadius="50dp" />
<stroke android:width="1dp" android:color="#BABABA" />
<solid android:color="#ffffff"/>
padding android:left="20dp" android:top="20dp"
android:right="20dp" android:bottom="20dp" />
</shape>
Image is below:
(https://imghostr.com/BwBwqrc1)

Design JavaFX View with FXML and Java Code

I have created my view for a JavaFX project using FXML. I was wondering if it's possible to add a few more items to the view pragmatically in controller class?
For example, how can I add another set of Text and TextField in my controller file?
FXML
<AnchorPane prefHeight="400.0" prefWidth="228.0">
<children>
<Text layoutY="10.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Selected User:" GridPane.rowIndex="0" />
<Text layoutY="45.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Username :" GridPane.rowIndex="1" />
<TextField fx:id="username" layoutY="55.0" GridPane.rowIndex="2" />
<Text layoutY="100.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Address :" GridPane.rowIndex="3" />
<TextField fx:id="address" layoutY="110.0" GridPane.rowIndex="4" />
<Text layoutY="155.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Web Page :" GridPane.rowIndex="5" />
<TextField fx:id="WP" layoutY="165.0" GridPane.rowIndex="6" />
<Text layoutY="210.0" strokeType="OUTSIDE" strokeWidth="0.0" text="State :" GridPane.rowIndex="7" />
<Text layoutY="265.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Login Name :" GridPane.rowIndex="9" />
<TextField fx:id="login_Name" layoutY="275.0" GridPane.rowIndex="10" />
<Button fx:id="btnSave" layoutX="50.0" layoutY="320.0" mnemonicParsing="false" onAction="#btnSaveClicked" text="Save" />
<Button fx:id="btnSave" layoutX="35.0" layoutY="365.0" mnemonicParsing="false" onAction="#btnDeleteUserClicked" text="Delete User" />
<Button fx:id="btnAddNew" layoutX="30.0" layoutY="410.0" mnemonicParsing="false" onAction="#btnAddeNewClicked" text="Add New User" />
<TextField fx:id="state" layoutX="-2.0" layoutY="222.0" />
</children>
</AnchorPane>
Adding New Nodes in FXML
I would say, you should always add new nodes to the FXML unless you have a very good reason not to. Adding nodes to FXML is as easy as adding an extra line to the existing FXML.
<AnchorPane prefHeight="400.0" prefWidth="228.0">
<children>
...
<Text fx:id="newText"/>
<TextField fx:id="newTextField"/>
</children>
</AnchorPane>
These new nodes will be reflected in the scene graph instantaneously and you can bind them to the controller using their fx:id's.
Adding New Nodes in Controller
First, you should have a fx:id defined for the AnchorPane in order to access it in the controller.
<AnchorPane fx:id="anchorPane" prefHeight="400.0" prefWidth="228.0">
<children>
...
</children>
</AnchorPane>
You can then define the new controls and add them the to AnchorPane in the controller.
public class MyController implements Initializable {
#FXML
private AnchorPane anchorPane;
...
public void intialize() {
...
Text newText = new Text("Some Text");
TextField newTextField = new TextField();
anchorPane.getChildren().addAll(newText, newTextField);
...
}
}

fxml file not behaving as expected in OS X

I am using an fxml file to to create my java fx UI.
the file is:-
<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<AnchorPane fx:id="ap" maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="480.0" prefWidth="840.0" xmlns="http://javafx.com/javafx/8.0.65"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.Buildsapp.Main.BuildsController">
<children>
<VBox prefHeight="200.0" prefWidth="100.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox alignment="CENTER_LEFT" spacing="20.0" VBox.vgrow="NEVER">
<padding>
<Insets bottom="12.0" left="12.0" right="12.0" top="12.0" />
</padding>
<children>
<GridPane hgap="10.0" HBox.hgrow="NEVER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0"
vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label prefHeight="21.0" prefWidth="88.0" text="Platform" />
<ComboBox fx:id="versionCombo" prefHeight="31.0"
prefWidth="108.0" GridPane.rowIndex="1">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="Win" />
<String fx:value="Mac" />
</FXCollections>
</items>
<value>
<String fx:value="Mac" />
</value>
</ComboBox>
<Label prefHeight="21.0" prefWidth="80.0" text="Product"
GridPane.columnIndex="1" />
<ComboBox fx:id="verCombo" prefHeight="31.0" prefWidth="127.0"
promptText="build" GridPane.columnIndex="1" GridPane.rowIndex="1">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="build" />
<String fx:value="build2" />
</FXCollections>
</items>
</ComboBox>
<Label text="Version" GridPane.columnIndex="2" />
<ComboBox fx:id="versionNo" prefHeight="31.0"
prefWidth="109.0" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<Label prefHeight="21.0" prefWidth="60.0" text="Server"
GridPane.columnIndex="3" />
<ComboBox fx:id="locCombo" prefHeight="31.0" prefWidth="103.0"
GridPane.columnIndex="3" GridPane.rowIndex="1">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="SJ" />
<String fx:value="MN" />
</FXCollections>
</items>
<value>
<String fx:value="SJ" />
</value>
</ComboBox>
<Button fx:id="downloadButton" minWidth="80.0"
mnemonicParsing="false" text="Download" GridPane.columnIndex="4"
GridPane.rowIndex="1" />
<Button fx:id="installButton" minWidth="80.0"
mnemonicParsing="false" text="Install" GridPane.columnIndex="5"
GridPane.rowIndex="1" />
<Button fx:id="locButton" mnemonicParsing="false"
prefHeight="31.0" prefWidth="120.0" text="Open Folder"
GridPane.columnIndex="6" GridPane.rowIndex="1" />
</children>
</GridPane>
</children>
</HBox>
<TableView fx:id="tableView" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="builds" prefWidth="482.0" text="Builds" />
<TableColumn fx:id="date" minWidth="0.0" prefWidth="500.0"
text="Date" />
</columns>
</TableView>
</children>
</VBox>
</children>
</AnchorPane>
It works fine in windows while in mac when I launch the app the app window does not appear as expected but it appears as a small window on the top left corner.
The similar issue is appearing with the progress dialog which I am using it works fine in Windows but in mac(OS X) when the app is expanded like when app window size is maximum the progress dialog is also covering the whole display screen while I have given fixed size to scene window.
This is my progress bar code:-
public ProgressBar startProgressBar() {
primaryStage = new Stage();
ProgressBar pb = new ProgressBar(0);
//ProgressIndicator pi = new ProgressIndicator(0);
//pi.progressProperty().bind(pb.progressProperty());
HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(pb);
Scene scene = new Scene(hb, 300, 100);
primaryStage.setScene(scene);
primaryStage.setTitle("Downloading Build...");
primaryStage.show();
return pb;
}
I am able find the solution for the first issue that can be solved my fixing the minHight and minWidth of the anchor panel to some value in fxml file instead of infinity but I am still not able to find the solution for the second issue.

LoadException with FXML created with Scene Builder

I've generated FXML in Scene Builder:
<?xml version="1.0" encoding="UTF-8"?>
<?scenebuilder-preview-i18n-resource ../lang/ru_RU.properties?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" fx:id="mainStagePane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="UI.MainStageController">
<children>
<SplitPane dividerPositions="0.6596244131455399" focusTraversable="true" prefHeight="-1.0" prefWidth="1280.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="160.0">
<items>
<AnchorPane id="rootPane" fx:id="pane3d" prefHeight="930.0" prefWidth="1280.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Accordion id="accordeon" fx:id="accordion" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<panes>
<TitledPane animated="true" text="%3dSceneSettings" fx:id="x2">
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Slider fx:id="farClipSlider" layoutY="50.0" majorTickUnit="10.0" max="100.0" min="-100.0" minorTickCount="1" prefWidth="337.0" showTickLabels="true" showTickMarks="true" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="75.0" />
<TextField layoutY="14.0" prefWidth="55.0" AnchorPane.rightAnchor="217.0" />
<Slider fx:id="distanceSlider" blockIncrement="25.0" layoutX="14.0" layoutY="133.0" majorTickUnit="50.0" max="500.0" min="-500.0" minorTickCount="25" prefWidth="399.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" />
<VBox layoutY="364.0" prefHeight="200.0" prefWidth="100.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0">
<children>
<HBox prefHeight="-1.0" prefWidth="-1.0">
<children>
<Label text="Label" />
<TextField prefWidth="55.0" />
</children>
</HBox>
<Slider fx:id="nearClipSlider" blockIncrement="1.0" majorTickUnit="10.0" max="100.0" min="-100.0" minorTickCount="1" prefWidth="338.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="0.0" />
</children>
</VBox>
<Label layoutX="104.0" layoutY="17.0" text="Label" />
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane animated="true" expanded="false" text="%3dModelSettings" fx:id="x1">
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</TitledPane>
</panes>
</Accordion>
</children>
</AnchorPane>
</items>
</SplitPane>
<ToolBar maxHeight="30.0" minHeight="30.0" prefHeight="30.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<items>
<ProgressBar fx:id="loadProgressBar" disable="false" prefWidth="200.0" progress="0.0" visible="true" />
</items>
</ToolBar>
<TabPane prefHeight="160.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab text="%file">
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button alignment="CENTER" graphicTextGap="4.0" mnemonicParsing="false" prefHeight="90.0" prefWidth="90.0" text="%openFile" textAlignment="CENTER" textOverrun="ELLIPSIS" underline="false" wrapText="true" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="14.0" />
<Separator layoutX="170.0" orientation="VERTICAL" prefHeight="200.0" AnchorPane.bottomAnchor="10.0" AnchorPane.topAnchor="10.0" />
</children>
</AnchorPane>
</content>
</Tab>
<Tab text="%analysis">
<content>
<AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<Button mnemonicParsing="false" prefHeight="90.0" prefWidth="90.0" text="Button" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="14.0" />
</children>
</AnchorPane>
</content>
</Tab>
</tabs>
</TabPane>
</children>
</AnchorPane>
But suddenly I received the following exception:
javafx.fxml.LoadException:
/D:/Projects/CastAnalytics/out/production/CastAnalytics/UI/MainStage.fxml
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2592)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2570)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2416)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3160)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3121)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3094)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3070)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3062)
at core.CastAnalytics.start(CastAnalytics.java:32)
at com.sun.javafx.application.LauncherImpl$8.run(LauncherImpl.java:837)
at com.sun.javafx.application.PlatformImpl$7.run(PlatformImpl.java:331)
at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:297)
at com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:294)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$6.run(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.NullPointerException
at UI.MainStageController.set(MainStageController.java:98)
at UI.MainStageController.initialize(MainStageController.java:34)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2523)
... 18 more
What does it mean and how can I fix it?
Well, you've got a null pointer at line 98 of MainStageController....
If I had to guess, I'd say that one of the #FXML variables you've defined in your Controller isn't named the same as in your FXML file, so you're getting a NPE.
You'd have to paste the relevant MainStageController.java code for anyone to know more.
Please post the offending line or SSCE if possible. I agree with jhsheets and your approach double checking the variable names against your fx:id names. I have encountered this exact error/situation myself at exactly the same place (in the initialize method trying to do some post-loading initialization) where a small typo in my fx:I'd caused an NPE. But it would be good to know what is going on in the set method where the NPE originates.

100% height XUL elements

I have this deck in a Firefox sidebar (XUL):
<deck id="mydeck" selectedIndex="0">
<vbox id="myscreen1">
...
</vbox>
<vbox id="myscreen2">
<vbox flex="3" minheight="150">
...
</vbox>
<splitter collapse="after" resizeafter="farthest">
<grippy height="10" align="end" />
</splitter>
<vbox flex="1" minheight="125">
...
</vbox>
</vbox>
</deck>
I'm trying to get #myscreen2 to take up the whole sidebar vertically. How do I achieve this?
Right now it only uses the minimum height set for the two boxes. I've tried to set height: 100% and flex="1" on the deck itself and #myscreen2, but it's not working.
I really don't like the available XUL documentation, but I managed to come up with a solution:
<deck id="mydeck" selectedIndex="0" flex="1">
<vbox id="myscreen1">
...
</vbox>
<vbox id="myscreen2">
<vbox flex="3" minheight="150">
...
</vbox>
<splitter collapse="after" resizeafter="farthest">
<grippy height="10" align="end" />
</splitter>
<vbox flex="1" minheight="125">
...
</vbox>
</vbox>
</deck>
The key was to have flex="1" on the deck. Not sure why it wasn't working when I tried it the first time.

Resources