Why white borders in JavaFX Polyline? - javafx

xml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Polyline?>
<Group xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Polyline points="0.0, 0.0, 100.0, 0.0" strokeLineCap="BUTT" strokeType="CENTERED" strokeWidth="15.0">
</Polyline>
</children>
</Group>
Someone knows why, when opening the above .fxml in Scene Builder, I see white borders on the down side and on the right side of the Polyline?
Note: there are no css nor hard-coded dimensions associated with the above fxml. I open just the plain fxml as shown.

Related

JavaFX Custom Component Does not Resize as Expected

I have a custom JavaFX component that is basically just a combination of a pane and textfield contained within a VBox.
What I want to do is have the bloody image turn brighter red when the textfield has focus or the mouse is over the VBox as a whole, because I think it would look nice. As of right now, my plan for this is just doing it programmatically. I am unaware of how I could do this using just CSS (Let me know if this is possible though, but this isn't related to the question).
The problem
The problem I am having is that when I try to resize the component along the x-axis using the component's pref width setting, the component doesn't visually stretch / resize, it just stays the same. When I change the pref size of the VBox in the original components fxml file, the textfield and pane expand as well. I could use CSS to set the pref width for all the elements within the custom component / the VBox in the CSS for scenes that would use the component, but I want to have the component automatically expand to fill their containers and I want so just easily be able to resize it within scene builder without changing CSS. Basically the underlying problem is I don't know how to get the VBox to resize when the component resizes. I was thinking I could add a custom field to do this but I am assuming there is an easier way of doing this, as the situation I am in would seem to be common, even if I can't find a solution for it when searching.
For reference here is the fxml for the custom component:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<VBox maxWidth="1.7976931348623157E308" styleClass="bloody-text-field" stylesheets="#../CSS/BloodyTextField.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextField fx:id="textField" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" />
<Pane fx:id="bloodyPane" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="35.0" minWidth="-Infinity" styleClass="bloody-pane" />
</children>
</VBox>
Here is the CSS for the custom component. The image shouldn't be important (Its just tileable in the x dimension) so I wont include it.
.bloody-text-field .text-field {
-fx-font-family: chiller;
-fx-font-size: 32px;
-fx-text-fill: #eb0900;
-fx-text-alignment: center;
-fx-alignment: center;
-fx-background-color: rgba(0.5, 0, 0, 0.0);
-fx-prompt-text-fill: #841200;
}
.bloody-text-field .bloody-pane {
-fx-background-repeat: repeat-x;
-fx-background-size: contain;
-fx-background-image: url("../Images/blood-drip-tileable.png");
}
Here is a fxml file that explains what I want to happen.
<?xml version="1.0" encoding="UTF-8"?>
<?import controls.BloodyTextField?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<BloodyTextField layoutX="32.0" layoutY="50.0" prefHeight="91.0" prefWidth="386.0" />
<Text layoutX="32.0" layoutY="45.0" strokeType="OUTSIDE" strokeWidth="0.0" text="I would expect this to expand until it fills the pref width" />
<VBox layoutX="32.0" layoutY="186.0" prefHeight="200.0" prefWidth="462.0">
<children>
<BloodyTextField />
<BloodyTextField />
</children>
</VBox>
<Text layoutX="32.0" layoutY="182.0" strokeType="OUTSIDE" strokeWidth="0.0" text="I would expect these two components to expand to fill the vbox's width" />
</children>
</Pane>
Thanks in advance for the guidance and help :)

Using Unicode characters with JavaFX

I've been playing around with swing for some time and decided to check out FX now. So far I'm finding it a lot easier and more fun to work with as compared to swing but I've run into a small speed bump and after hours of looking around I just can't find a solution.
I am unable to use \u when I try to add it through the fxml file It works fine if I don't use the fxml but I want to use the scene builder as it is more convenient.
Here's the small piece of code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.131" fx:controller="baitform.designDocController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" onAction="#handleButtonAction" text="Click Me!" />
<Label layoutX="145.0" layoutY="129.0" text="\u0644\u0627\u062B\u0627\u0646\u0649" />
</children>
</AnchorPane>
The error I keep getting is
Caused by: javafx.fxml.LoadException: Invalid escape sequence.
Not sure if relevant, but I'm using jdk1.8.0_131 & netbeans 8.2
If anyone could point me in the right direction here I'd really appreciate it.
FXML is an XML, and so you need to use XML escaping:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.131" fx:controller="baitform.designDocController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" onAction="#handleButtonAction" text="Click Me!" />
<Label layoutX="145.0" layoutY="129.0" text="لاثانى" />
</children>
</AnchorPane>
That being said, if you are able to input the characters, you can just insert them as is.
See also: https://www.w3.org/International/questions/qa-escapes

JavaFX ScrollPane scrollbar is disabled

I have built a layout in SceneBuilder which has a ScrollPane (inside of a StackPane) containing a StackPane containing a Group (aligned to center-left) containing an ImageView. For some reason, whether I preview within SceneBuilder with Ctrl+P or run in my program, the horizontal scrollbar is disabled. The scrollbar does show that there is more to the right to be scrolled to, but I cannot scroll to it. It looks like this:
And here is the FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Group?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.effect.DropShadow?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: white;" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
<center>
<StackPane prefHeight="150.0" prefWidth="200.0" style="-fx-background-color: white;" BorderPane.alignment="CENTER">
<children>
<ScrollPane id="scoreScrollPane" fitToHeight="true" hbarPolicy="ALWAYS" prefHeight="0.0" prefWidth="0.0" vbarPolicy="NEVER">
<content>
<StackPane alignment="CENTER_LEFT">
<children>
<Group id="scoreGroup" StackPane.alignment="CENTER_LEFT">
<children>
<ImageView id="scoreImage" fitHeight="150.0" fitWidth="3000.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#Untitled.png" />
</image>
</ImageView>
</children>
</Group>
</children>
</StackPane>
</content>
</ScrollPane>
<HBox id="toolbar" alignment="TOP_CENTER" prefHeight="100.0" prefWidth="200.0" spacing="8.0">
<children>
<Button id="recordButton" mnemonicParsing="false" text="Record" />
<Button id="stopButton" mnemonicParsing="false" text="Stop" />
</children>
<effect>
<DropShadow />
</effect>
</HBox>
</children>
</StackPane>
</center>
</BorderPane>
I've tried a horizontal scroll policy of both AS_NEEDED and ALWAYS.
You have numerous problems (most important is that the HBox with your controls covers your ScrollPane, intercepting that would otherwise go the ScrollPane):
Set preserveRatio="false" instead of preserveRatio="true" for your ImageView, otherwise the image may not grow to the fitWidth you provide (because it may hit the fitHeight limit first and not grow the width anymore).
Set maxHeight="-Infinity" on your HBox, (this will ensure that the maximum height of the HBox does not grow above the preferred height for the HBox, otherwise the HBox will intercept the mouse clicks intended for your ScrollPane). Either this, or set pickOnBounds="false" for the HBox, so that the HBox does not intercept mouse clicks for the ScrollPane even though it overlays the ScrollPane.
Note: to debug layout sizes, sometimes it is useful to temporarily add a background or border to a region to see it's true size, for example style="-fx-background-color: red;".
Also rather than placing your controls and image in a StackPane, which overlays content, maybe you might want to use a VBox instead, which instead lays things out vertically rather than on top of each other.

How to use the CSS file in JavaFX project?

i'm trying to build a JavaFX Application and i want to attach the CSS file in the FXML file but when i try to run the app i get a problem like: Property "stylesheets" does not exist or is read-only. in the console i don't know what is the problem exactly (note if i delete the CSS file everything works fine).
The CSS file "csstyle.css" contains:
/*
* Empty Stylesheet file.
*/
.mainFxmlClass {
-fx-background-color: blue;
}
Also i wrote in the Stylesheet in the FXML file the name of the CSS file also in the Style Class : .mainFxmlClass .
So i want to know the error please help me and thanks :)
You have two problems:
The first one is already solved here. Remove
stylesheets="#csstyle.css"
and add it right after the <children> tags of your root container. Since you don't show how is your FXML file, this is how it should look like:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import java.net.*?>
<AnchorPane styleClass="mainFxmlClass" ...>
<children>
...
</children>
<stylesheets>
<URL value="#cssstyle.css" />
</stylesheets>
</AnchorPane>
The second is this one:
styleClass=".mainFxmlClass"
Remove the dot:
styleClass="mainFxmlClass"
EDIT
Given these solutions didn't work and the fact that the OP is using JDK 7 with JavaFX 2.0 these other solutions may help:
Replace:
styleClass="mainFxmlClass"
with:
<styleClass>
<String fx:value="mainFxmlClass"/>
</styleClass>
So your FXML will be like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import java.net.*?>
<AnchorPane ...>
<children>
...
</children>
<styleClass>
<String fx:value="mainFxmlClass"/>
</styleClass>
<stylesheets>
<URL value="#cssstyle.css" />
</stylesheets>
</AnchorPane>
And try it again.
Finally, if it is not working, remove the <stylesheets> tags, and set the stylesheet file on your Scene:
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("cssstyle.css").toExternalForm());
So your FXML will be like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<AnchorPane ...>
<children>
...
</children>
<styleClass>
<String fx:value="mainFxmlClass"/>
</styleClass>
</AnchorPane>
It's really advisable updating JavaFX to newer versions (2.2.45 is the last one for Java 7), and benefit from many new features added.

JavaFX: how to make a proper vertical toolbar?

I want to make a vertical toolbar with buttons arranged vertically. Using JavaFX 2.2 that is included in JDK 7, in Linux Mint.
The screenshot shows the problem:
The FXML I am using looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<?language javascript?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane prefHeight="800.0" prefWidth="700.0" styleClass="root" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<top>
<ToolBar>
<items>
<Button text="Test" />
</items>
</ToolBar>
</top>
<left>
<ToolBar orientation="VERTICAL" style="-fx-background-color: blue;">
<items>
<Region style="-fx-padding:10;" />
<Button rotate="-90" text="Project" style="-fx-label-padding:1;"/>
<Region style="-fx-padding:10;" />
<Button rotate="-90" text="Structure" />
</items>
</ToolBar>
</left>
<center>
<HBox>
<children>
</children>
</HBox>
</center>
<bottom>
<ToolBar prefHeight="18.0" prefWidth="472.0">
<items>
<Region styleClass="spacer" />
<HBox>
<children>
</children>
</HBox>
</items>
</ToolBar>
</bottom>
</BorderPane>
The proper toolbar in my definition is: buttons are placed correctly and the toolbar is as wide as the width of the buttons. The blue color indicates how wide the toolbar currently is.
Wrap your rotated tool items in a Group, then the in-built layout of toolbar will know that the rotation is a permanent one which should be taken into account for layout calculations and not just a temporary thing which might be used for animations. Read the javadoc for Group, where it talks about layout bounds calculations to better understand this.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="100.0" style="-fx-background-color: cornsilk;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ToolBar orientation="VERTICAL" style="-fx-base: palegreen;">
<items>
<Group>
<children>
<Button rotate="-90.0" style="-fx-base: gold;" text="Project" />
</children>
</Group>
<Group>
<children>
<Button rotate="-90.0" style="-fx-base: khaki;" text="Structure" />
</children>
</Group>
</items>
</ToolBar>
</children>
</HBox>
Update 24th April 2017
The above solution is fine as far as it goes, but does suffer from an issue in that the buttons in the toolbar misalign when they receive focus.
What a group does is size itself based upon its contents. When the size of the contents changes, the size of the group also changes. When a button or control gets focus in JavaFX it gets a focus ring around the control. The display for the focus ring is defined in CSS and contains negative values for background inset display. The result is that, when a control is focused, it is slightly larger than when it is not focused. Normally, when you use a standard layout pane, this is not an issue as the layout pane will just ignore the background insets for layout purposes. A group however takes the full size into account and does not ignore the focus ring. The result is that a group that consists of only a control will change in size slightly when it is focused or unfocused. This presents an issue with the solution above because, when a button becomes focused, it will get slightly larger and the shift in layout in the toolbar, which is not ideal.
The solution to the focus shift problem in the above code is to just rotate the entire ToolBar within a group rather than rotating each button within a group per button. This works fine, but then presents some other issues such as the ToolBar not taking up the entire available area at the left side of the scene (due to wrapping it in a group removing the dynamic layout properties of the ToolBar). To get around this, a binding in code can be used to size the ToolBar to the available area of its parent layout container.
So we end up with the slightly more verbose solution below:
skinsample/toolbar.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.control.ToggleGroup?>
<BorderPane fx:id="border" prefHeight="200.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="skinsample.VerticalToolbarController">
<left>
<Group>
<fx:define>
<ToggleGroup fx:id="selectedTool"/>
</fx:define>
<ToolBar fx:id="toolbar" rotate="-90.0" style="-fx-base: palegreen;">
<Pane HBox.hgrow="ALWAYS" />
<ToggleButton style="-fx-base: khaki;" text="Structure" toggleGroup="${selectedTool}"/>
<ToggleButton style="-fx-base: gold;" text="Project" toggleGroup="${selectedTool}" selected="true"/>
</ToolBar>
</Group>
</left>
</BorderPane>
skinsample/VerticalToolbarController.java
package skinsample;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.BorderPane;
public class VerticalToolbarController {
#FXML
private BorderPane border;
#FXML
private ToolBar toolbar;
public void initialize() {
toolbar.minWidthProperty().bind(Bindings.max(border.heightProperty(), toolbar.prefWidthProperty()));
}
}
skinsample/ToolDisplayApp.java
package skinsample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ToolDisplayApp extends Application {
#Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("toolbar.fxml"));
Scene scene = new Scene(loader.load());
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Notes:
This solution also demonstrates use of ToggleButtons rather than standard buttons within the ToolBar.
We also eliminate the default overflow behavior of the ToolBar (as it seems a little annoying in the vertical toolbar situation), using:
toolbar.minWidthProperty().bind(Bindings.max(border.heightProperty(), toolbar.prefWidthProperty()));
If you want to retain the overflow behavior, then use:
toolbar.prefWidthProperty().bind(border.heightProperty());
An alternate solution to the focus issue (using CSS to remove the focus ring entirely), is presented in:
JavaFX - How to prevent Toolbar from changing width on button state changes.

Resources