I am working on a chatbot project in java and for the GUI I am using JavaFX, and IDE eclipse oxygen and scene builder 8.4.1.
I am having a problem adding a background image to a text area. here is a screen shot of what I did and it just shows nothing(not even an error).
following is the fxml code generated by scene builder:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<top>
<AnchorPane prefHeight="56.0" prefWidth="600.0" style="-fx-background-color: blue;" BorderPane.alignment="CENTER">
<children>
<ImageView fitHeight="51.0" fitWidth="79.0" layoutX="23.0" layoutY="20.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../../Downloads/background.jpg" />
</image></ImageView>
<Label layoutX="118.0" layoutY="36.0" text="Ibot" />
</children>
</AnchorPane>
</top>
<center>
<TextArea editable="false" prefHeight="200.0" prefWidth="200.0" style="-fx-background-image: url("../../../Downloads/background.jpg"); -fx-background-repeat: stretch;" BorderPane.alignment="CENTER" />
</center>
<bottom>
<HBox BorderPane.alignment="CENTER">
<children>
<TextField prefHeight="25.0" prefWidth="476.0" promptText="Type in here" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets />
</HBox.margin>
</TextField>
<Region prefHeight="25.0" prefWidth="60.0" />
<Button mnemonicParsing="false" prefHeight="25.0" prefWidth="57.0" text="Send">
<HBox.margin>
<Insets />
</HBox.margin>
</Button>
</children>
<BorderPane.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</BorderPane.margin>
<padding>
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
</padding>
</HBox>
</bottom>
</BorderPane>
It's probably not working because as specify in JavaFX CSS Reference Guide the TextArea is a association of two substructure: a ScrollPane and a Region. You have to change the style of those.
In CSS this should work:
#text-area-id .content{
-fx-background-image : url("the_path_to_your_image")
/* others properties */
}
Edit to answer comment:
For a button you just need to set the property -fx-background-image:
#your-button{
-fx-background-image : url("the_path_to_your_image")
}
Related
I am trying to achieve this layout using FXML and GridPane.
what I achieved is this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>
<?import java.lang.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<GridPane fx:controller="com.mycompany.mavenproject1.PrimaryController" xmlns:fx="http://javafx.com/fxml" alignment="center">
<Label fx:id="label" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.hgrow="always" GridPane.vgrow="always" />
<TextField fx:id="a" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField fx:id="b" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<TextField fx:id="c" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
<Button fx:id="solveButton" text="Solve" onAction="#solve" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<Button fx:id="clearButton" text="Clear" onAction="#clear" GridPane.columnIndex="0" GridPane.rowIndex="3" />
</GridPane>
Question: How do I make children actually fit the GridPane and why those textfields are not of the same size?
Another alternate way to achieve this is to just relay on the GridPane constraint features.
You can add Column/Row constraints and set the fillHeight/fillWidth to true and hgrow/vgrow policies to ALWAYS. Also set the desired nodes maxWidth/maxHeight to Infinity to auto stretch.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center">
<Label fx:id="label" text="Number Format Error !" maxWidth="Infinity" alignment="CENTER" GridPane.columnSpan="3"/>
<TextField fx:id="a" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField fx:id="b" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<TextField fx:id="c" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
<Button fx:id="solveButton" text="Solve" maxWidth="Infinity" maxHeight="Infinity" GridPane.columnSpan="3" GridPane.rowIndex="2" />
<Button fx:id="clearButton" text="Clear" maxWidth="Infinity" maxHeight="Infinity" GridPane.columnSpan="3" GridPane.rowIndex="3" />
<columnConstraints>
<ColumnConstraints fillWidth="true" hgrow="ALWAYS"/>
<ColumnConstraints fillWidth="true" hgrow="ALWAYS"/>
<ColumnConstraints fillWidth="true" hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="ALWAYS"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints fillHeight="true" vgrow="ALWAYS"/>
<RowConstraints fillHeight="true" vgrow="ALWAYS"/>
</rowConstraints>
</GridPane>
How do I make children actually fit the GridPane [...]?
You can wrap a child node in an AnchorPane and set the anchors to zero.
[...] and why those textfields are not of the same size?
I don't know but you can use ColumnConstraints and set each column width to 33.33 %.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane alignment="center" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.mycompany.mavenproject1.PrimaryController">
<columnConstraints>
<ColumnConstraints percentWidth="33.33"/>
<ColumnConstraints percentWidth="33.33"/>
<ColumnConstraints percentWidth="33.33"/>
</columnConstraints>
<AnchorPane GridPane.columnSpan="3" GridPane.hgrow="always" GridPane.vgrow="always">
<children>
<Label fx:id="label" alignment="CENTER" style="-fx-background-color: tomato;" text="Number format error!"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0"/>
</children>
</AnchorPane>
<TextField fx:id="a" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField fx:id="b" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<TextField fx:id="c" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
<AnchorPane GridPane.columnSpan="3" GridPane.rowIndex="2">
<Button fx:id="solveButton" onAction="#solve" text="_Solve" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/>
</AnchorPane>
<AnchorPane GridPane.columnSpan="3" GridPane.rowIndex="3">
<Button fx:id="clearButton" onAction="#clear" text="_Clear" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/>
</AnchorPane>
</GridPane>
I made an FXML in the Scenebuilder with a Tableview and Pagination.
But I am having trouble to get the pagination to work, especially the PageFactory.
I have following code:
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Pagination?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="recordsOverview" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="accentor.overview.RecordsOverviewController">
<children>
<Pagination fx:id="paginator" onMouseClicked="#pageClicked" prefHeight="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="340.0" />
<HBox alignment="TOP_RIGHT" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="60.0">
<children>
<Label prefHeight="25.0" text="Search:" />
<TextField prefHeight="25.0" prefWidth="137.0" />
<Label prefHeight="25.0" text="Sort:" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<Label prefHeight="52.0" text="Records" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0">
<font>
<Font size="48.0" />
</font>
</Label>
<TableView fx:id="table" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="100.0">
<columns>
<TableColumn fx:id="trackid" text="#" />
<TableColumn fx:id="title" text="Title" />
<TableColumn fx:id="length" text="Length" />
<TableColumn fx:id="album" text="Album" />
<TableColumn fx:id="artists" text="Artist(s)" />
</columns>
</TableView>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</AnchorPane>
Controller:
public void fillTable(int page) {
this.dataModel.setTracksPage(page);
this.table.setItems(FXCollections.observableArrayList(this.dataModel.getTracks().getData()));
this.paginator.setCurrentPageIndex(page);
}
#Override
public void showOverview() {
recordsOverview.setVisible(true);
}
#Override
public void setDataModel(DataModel dataModel) {
if (this.dataModel == null) {
this.dataModel = dataModel;
}
fillTable(1);
paginator.setPageCount(this.dataModel.getTracks().getTotalPages());
this.paginator.setPageFactory((Integer pageIndex) -> {
fillTable(pageIndex);
return null; // ???
}
);
}
I just want to fill the table with new data, but returning null gives me errors.
If I return something else like return new BorderPane(table), It doesn't work either, same error.
How can I solve this issue?
Your page factory needs to return the node that will be displayed as the "page". The Pagination will then manage that node and make it part of the scene graph under it. What you want to do is display the TableView in the pagination, so you should return it from the page factory.
You didn't post any of the stack traces from the errors you mention, but I'm guessing that what's happening is that when you return the table, you get an error because the TableView is already part of the scene graph, and nodes can't exist in two different places.
One solution is to omit the table entirely from the FXML, and just define it in the controller (set it up in the initialize() method, then return the reference to it from the page factory).
If you still want it defined in the FXML file, you can define elements in FXML which are not part of the scene graph by wrapping them in a <fx:define> block.
So your FXML would look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Pagination?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<AnchorPane fx:id="recordsOverview" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="accentor.overview.RecordsOverviewController">
<fx:define>
<TableView fx:id="table" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="100.0">
<columns>
<TableColumn fx:id="trackid" text="#" />
<TableColumn fx:id="title" text="Title" />
<TableColumn fx:id="length" text="Length" />
<TableColumn fx:id="album" text="Album" />
<TableColumn fx:id="artists" text="Artist(s)" />
</columns>
</TableView>
</fx:define>
<children>
<Pagination fx:id="paginator" onMouseClicked="#pageClicked" prefHeight="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="340.0" />
<HBox alignment="TOP_RIGHT" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="60.0">
<children>
<Label prefHeight="25.0" text="Search:" />
<TextField prefHeight="25.0" prefWidth="137.0" />
<Label prefHeight="25.0" text="Sort:" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
<ChoiceBox prefHeight="25.0" prefWidth="100.0" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</HBox>
<Label prefHeight="52.0" text="Records" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0">
<font>
<Font size="48.0" />
</font>
</Label>
</children>
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding>
</AnchorPane>
and then you do
this.paginator.setPageFactory((Integer pageIndex) -> {
fillTable(pageIndex);
return table;
}
);
I have a BoarderPane (decoration: UTILITY) where a ButtonBar with two buttons is put to BOTTOM:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pw.yaps.client.jfx.view.SettingsViewController">
<bottom>
<ButtonBar BorderPane.alignment="CENTER">
<buttons>
<Button disable="true" mnemonicParsing="false" text="OK" />
<Button cancelButton="true" mnemonicParsing="false" onAction="#handleCancelAction" text="Cancel" />
</buttons>
<padding>
<Insets bottom="12.0" right="12.0" />
</padding>
</ButtonBar>
</bottom>
</BorderPane>
When the Stage is NOT resizable the layout looks like that:
but when I set it resizable it looks different:
How can this behavior be avoided?
When I increase the window, the inner elements stay at the same size.
I want that when I increase the window, that the elements also get larger/scale
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane cacheHint="SCALE_AND_ROTATE" focusTraversable="true" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<TableView fx:id="finalTable" layoutX="27.0" layoutY="358.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="190.0" prefWidth="766.0" />
<Label layoutX="27.0" layoutY="21.0" prefHeight="25.0" prefWidth="149.0" text=" Quell-Datei" />
<TableView fx:id="sourceTable" editable="true" layoutX="27.0" layoutY="50.0" maxHeight="900.0" maxWidth="900.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="190.0" prefWidth="766.0" />
<Label layoutX="27.0" layoutY="329.0" prefHeight="25.0" prefWidth="149.0" text=" Konvertierte-Datei" />
<Button fx:id="linkBtn" layoutX="313.0" layoutY="282.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#linkAction" prefHeight="30.0" prefWidth="90.0" text="Verbinden" />
<Button fx:id="splitBtn" layoutX="437.0" layoutY="282.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#splitAction" prefHeight="30.0" prefWidth="90.0" text="Trennen" />
</children>
</AnchorPane>
Im working with SceneBuilder 2.0, and I have also tried to "anchor" a button
(see here: http://i.imgur.com/GZyL5xC.png)
...but the scaling is completely wrong (see here: http://i.imgur.com/hmMi1p3.png)
I searched the whole internet for an answer, but I found nothing that could help.
Well your layout is typically a VBox layout. If your Windows isn't at a fixed size this will be a good solution, because your Buttons stay at the same height and in the center of your window. The TableViews grow and shrink as you resize the window. Like you want.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Label prefHeight="25.0" prefWidth="149.0" text=" Quell-Datei" VBox.vgrow="NEVER" />
<TableView fx:id="sourceTable" editable="true" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
<Label />
<HBox alignment="CENTER" prefHeight="61.0" prefWidth="766.0" spacing="20.0" VBox.vgrow="NEVER">
<children>
<Button fx:id="linkBtn" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#linkAction" prefHeight="30.0" prefWidth="90.0" text="Verbinden" HBox.hgrow="NEVER" />
<Button fx:id="splitBtn" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#splitAction" prefHeight="30.0" prefWidth="90.0" text="Trennen" HBox.hgrow="NEVER" />
</children>
</HBox>
<Label prefHeight="25.0" prefWidth="149.0" text=" Konvertierte-Datei" VBox.vgrow="NEVER" />
<TableView fx:id="finalTable" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" />
</children>
<padding>
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
</padding>
</VBox>
I have got a SplitPane in a SplitPane -- both horizontal. I would like to avoid specifying absolute width/height. When I don't specify width/height, the second SplitPane is not shown:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="500.0" style="-fx-background-color: cornsilk;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<left>
<ToolBar orientation="VERTICAL">
<items>
<Group>
<children>
<Button rotate="-90.0" text="Project" />
</children>
</Group>
<Group>
<children>
<Button rotate="-90.0" text="Structure" />
</children>
</Group>
</items>
</ToolBar>
</left>
<center>
<SplitPane dividerPositions="0.25" style="-fx-background-color:red;">
<items>
<AnchorPane style="-fx-background-color:darkblue;"/>
<AnchorPane style="-fx-background-color:gold;">
<children>
<SplitPane dividerPositions="0.25">
<items>
<AnchorPane style="-fx-background-color:khaki;"/>
<AnchorPane style="-fx-background-color:lime;"/>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</center>
</BorderPane>
Defining the SplitPane with <SplitPane dividerPositions="0.25" AnchorPane.topAnchor="0.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"> fixes the problem, here is the MWE:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="700.0" style="-fx-background-color: cornsilk;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<left>
<ToolBar orientation="VERTICAL">
<items>
<Group>
<children>
<Button rotate="-90.0" text="Project" />
</children>
</Group>
<Group>
<children>
<Button rotate="-90.0" text="Structure" />
</children>
</Group>
</items>
</ToolBar>
</left>
<center>
<SplitPane dividerPositions="0.25" style="-fx-background-color:red;">
<items>
<AnchorPane style="-fx-background-color:green;"/>
<AnchorPane style="-fx-background-color:blue;">
<children>
<SplitPane dividerPositions="0.25" AnchorPane.topAnchor="0.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<items>
<AnchorPane style="-fx-background-color:black;"/>
<AnchorPane style="-fx-background-color:aqua;"/>
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
</center>
</BorderPane>