How to find FXML variable by id dynamically in javafx? - java

I am trying to create an HTML editor (learning purposes) and I am trying to make program as dynamic as possible. I want to find FXML variable, like TextField, by it's id and retrieve the text in the textfield when I press the button.
I have 2 Map variables set up
public FXMLDocumentController() {
this.HTMLtags = new HashMap<>();
HTMLtags.put("pressMeButton", "h2.fx-h2");
HTMLtags.put("setNewsMessageButton", "p.fx-message");
this.elementsMap = new HashMap<>();
elementsMap.put("pressMeButton", "newsTitle");
elementsMap.put("setNewsMessageButton", "newsMessage");
}
HTMLtags holds the button ID and HTML tag, which is going to be edited.
elementsMap holds button ID and TextView ID that it suppose to grab text from. Kinda like "binding specific button to specific textfield".
private void changeText(ActionEvent event) throws IOException {
Object source = event.getSource();
Button clickedButton = (Button) source;
System.out.println(HTMLtags.get(clickedButton.getId()));
System.out.println(elementsMap.get(clickedButton.getId()));
writeToHTML(HTMLtags.get(clickedButton.getId()), elementsMap.get(clickedButton.getId()));
}
Method above correctly retrieves IDs of buttons and HTML tags that need to be edited.
Here is the code that sets the text in the HTML
private void writeToHTML(String HTMLTag, String textField) {
File input = new File(filePath);
Document doc;
try {
doc = Jsoup.parse(input, "UTF-8");
Element head = doc.select(HTMLTag).first();
originalText = head.toString();
TextField textFieldName = new TextField();
textFieldName.setId(textField);
head.text(textFieldName.getText());
System.out.println("Original Text is: " + originalText);
System.out.println("Modified Text is: " + head);
Path path = Paths.get(filePath);
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll(originalText, head.toString());
Files.write(path, content.getBytes(charset));
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
The problem is that I dunno how to find and retrieve text from textfield specifically in this part of code
TextField textFieldName = new TextField();
textFieldName.setId(textField);
head.text(textFieldName.getText());
I want to do it dynamically without declaring each FXML element through
#FXML private TextField "name of the fx:id" and matching each element through loop.
I want to do it similar to the way I get ID/value of the button through ActionEvent.
EDIT:
here is the full FXML btw
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.66" xmlns:fx="http://javafx.com/fxml/1" fx:controller="newsletter.editor.FXMLDocumentController">
<children>
<ScrollPane fitToWidth="true" prefHeight="800.0" prefWidth="1280.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<VBox alignment="CENTER" prefHeight="450.0">
<children>
<HBox alignment="CENTER">
<children>
<Label alignment="CENTER" minHeight="25.0" minWidth="192.0" prefHeight="50.0" prefWidth="192.0" text="Newsletter Title" wrapText="true">
<font>
<Font size="18.0" />
</font>
</Label>
<TextField id="newsTitle" fx:id="newsTitle" prefHeight="28.0" prefWidth="180.0" promptText="Write here" HBox.hgrow="ALWAYS" />
</children>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<TextArea fx:id="newsMessage" prefHeight="100.0" prefWidth="766.0" />
</children>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0" />
<HBox prefHeight="100.0" prefWidth="200.0" />
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button fx:id="setNewsMessageButton" mnemonicParsing="false" onAction="#changeText" text="MAGIC" />
<Button fx:id="pressMeButton" mnemonicParsing="false" onAction="#changeText" text="Press Me for Magic">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
<Button fx:id="filePathButton" mnemonicParsing="false" onAction="#filePathSave" text="Select Path">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
<Button fx:id="popoverButton" mnemonicParsing="false" onAction="#popOverTrigger" text="PopOver Test">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</children>
<padding>
<Insets left="20.0" right="20.0" />
</padding>
</VBox>
</content>
</ScrollPane>
</children>
</AnchorPane>

You can perform an id lookup to find the TextField.
Parent parent = getTextFieldParent(); // the Parent (or Scene) that contains the TextFields
TextField textField = (TextField) parent.lookup("#myTextField");
if (textField != null)
String text = textField.getText();

Yes, your need method lookup(). Not only Parent class has this method, it also has at Panel classes like FlowPane, AnchorPane and many other. Also this method in Scene class.
But! This method looking only after scene show. I don't now, why it happens, but before Scene show(), lookup() only finds top-level panel. And after show() it finds element by id, like scene.lookup("#myId");
Symbol # is required.
Also lookup() method can find element without id, by the type.
Example: scene.lookup("FlowPane"); (without #) will find the first FlowPane in your .fxml file. And scene.lookupAll("ImageView"); will return the massive with all ImageView elements in scene.

Related

2 different lists in one ListView in JavaFX divided by a header

I am trying to implement an events list in one page in JavaFX, and I would like to display 2 lists: one for UPCOMING events and one for PAST events, both relative to the current date.
A lot of searches online lead me to using an ArrayAdaptor, but I am not allowed to use any other libraries except for JavaFX.
I would also like to divide these 2 lists by a header. Right now I am working with a base code:
/**
* Panel containing the list of persons.
*/
public class HomePage extends UiPart<Region> {
private static final String FXML = "home/HomePage.fxml";
private final Logger logger = LogsCenter.getLogger(HomePage.class);
#FXML
private ListView<Trip> tripListView;
public HomePage(ObservableList<Trip> tripList) {
super(FXML);
tripListView.setItems(tripList);
tripListView.setCellFactory(listView -> new TripListViewCell());
}
/**
* Custom {#code ListCell} that displays the graphics of a {#code Trip} using a {#code TripCard}.
*/
class TripListViewCell extends ListCell<Trip> {
#Override
protected void updateItem(Trip trip, boolean empty) {
super.updateItem(trip, empty);
if (empty || trip == null) {
setGraphic(null);
setText(null);
} else {
setGraphic(new HomePageTripCard(trip, getIndex() + 1).getRoot());
}
}
}
}
This is the .fxml code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/11" xmlns:fx="http://javafx.com/fxml/1">
<StackPane prefHeight="30.0" prefWidth="200.0" styleClass="stack-welcome" VBox.vgrow="NEVER">
<children>
<Label styleClass="label-welcome" text="Welcome-Message-Here" />
</children>
</StackPane>
<StackPane prefHeight="15.0" prefWidth="200.0" styleClass="stack-header" VBox.vgrow="NEVER">
<children>
<Label styleClass="label-header" text="TripList" />
</children>
</StackPane>
<StackPane>
<ListView fx:id="tripListView" prefWidth="247.0" VBox.vgrow="ALWAYS" />
<ListView fx:id="tripListView" prefWidth="247.0" VBox.vgrow="ALWAYS" />
</StackPane>
</VBox>
I tried using 2 different list views, for some reason it only shows up with one of the list views.
Does anyone have any tips on how to go about implementing 2 lists in one list view in JavaFX?
I just decided to use 2 list views instead, with each list view having their own list cells, both within a single VBox.
Implementation in the java file
tripListViewUpcoming.setItems(upcoming);
tripListViewUpcoming.setCellFactory(listViewUpcoming -> new TripListViewCellUpcoming());
tripListViewPast.setItems(past);
tripListViewPast.setCellFactory(listViewPast -> new TripListViewCellPast(upcoming.size()));
Implementation in the FXML file
<StackPane prefHeight="15.0" prefWidth="200.0" styleClass="trip-list-header" style="-fx-border-width: 0px 0px 2px 0px" VBox.vgrow="NEVER">
<children>
<Label styleClass="label-header" text="UPCOMING TRIPS" />
</children>
</StackPane>
<ListView fx:id="tripListViewUpcoming" prefWidth="247.0" style="-fx-background-color: #fff;" VBox.vgrow="ALWAYS" />
<StackPane prefHeight="15.0" prefWidth="200.0" styleClass="trip-list-header" style="-fx-border-width: 2px 0px 2px 0px" VBox.vgrow="NEVER">
<children>
<Label styleClass="label-header" text="PAST TRIPS" />
</children>
</StackPane>
<ListView fx:id="tripListViewPast" prefWidth="247.0" style="-fx-background-color: #fff;" VBox.vgrow="ALWAYS" />
The downside is that the second list view does not come immediately after the last cell in the first list view, and both list views scroll interdependently.

Root value already specified Exception in CustomController while loading a FXML

first of all: I have tried:
fxml loader exception "root value is already specified" I never specified a root value
javafx exception : Controller value already specified
LoadException: Root value already specified on custom control
But no solution worked for me: I deleted the fx:controller tag from my FXML -> Exception, added fx:root type="BorderPanealways the same Exception:
Caused by: java.lang.RuntimeException: javafx.fxml.LoadException: Root value already specified
When I remove the statement fxmlLoader.setRoot(this) from my custom controller no Exception is thrown but the layout is empty. For better understanding, below are my code snippets from my MainScreenController where I want to add the custom controller as child and my CustomController class ImageContainer
Help is appreciated!
Code snippet MainScreenController (only a snippet):
public class MainScreenController{
public TextField tf_userName;
public ListView lv_listView;
public FlowPane fp_contentFlowPane;
public SplitPane sp_splitPane;
public void onItemClicked(MouseEvent mouseEvent) throws IOException {
int index = lv_listView.getSelectionModel().getSelectedIndex();
if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
if (index >= 0) {
lv_listView.getItems().remove(index);
userList.remove(index);
}
}
else{
ImageContainer imgC = new ImageContainer(4,2,"location");
fp_contentFlowPane.getChildren().add(imgC);
}
}}
Code of my Custom controller, ImageContainer:
public class ImageContainer extends Pane {
public HBox hbx_elementContainer;
public Label lb_likeCount;
public Label lb_commentCount;
public Label lb_location;
public Label lb_accountHolder;
public ImageView iv_feedImage;
private String imageLink;
public ImageContainer(int likeCount, int commentCount, String location) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/image_container.fxml"));
fxmlLoader.setController(this);
fxmlLoader.setRoot(this);
try {
fxmlLoader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
this.lb_likeCount.setText(String.valueOf(likeCount));
this.lb_commentCount.setText(String.valueOf(commentCount));
this.lb_location.setText(location);
Image image = new Image("/sampleFoto.JPG");
iv_feedImage.setImage(image);
}
}
FXML file of the layout I want to set:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1">
<bottom>
<HBox fx:id="hbx_elementContainer" prefHeight="31.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<Label fx:id="lb_likeCount" contentDisplay="TOP" text="Label">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin></Label>
<Label fx:id="lb_commentCount" text="Label">
<HBox.margin>
<Insets right="20.0" />
</HBox.margin></Label>
<Label fx:id="lb_location" text="Label" />
<Label fx:id="lb_accountHolder" text="Label" />
<Button mnemonicParsing="false" text="Download">
<font>
<Font name="Arial Bold" size="11.0" />
</font>
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</bottom>
<center>
<AnchorPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="iv_feedImage" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</center>
</BorderPane>

Can't pass attribute betwewen scenes JAvaFX

I'm trying to pass a String between scenes in JavaFX, I already followed the some answers but it seems that they don't work because the string is null in the new scene.
Here's my MainControler:
public class FXMLDocumentController implements Initializable {
#FXML
private Button btn_signup;
#FXML
private TextField et_username;
#FXML
private PasswordField et_password;
#FXML
private Hyperlink link_login;
Stage prevStage;
public void setPrevStage(Stage stage){
this.prevStage = stage;
}
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
if(btn_signup == event.getSource()){
Conector conn = new Conector();
if (conn.checkUser(et_username.getText(), et_password.getText())) {
FXMLLoader myLoader = new FXMLLoader(getClass().getResource("FXMLTasker.fxml"));
Pane myPane = (Pane)myLoader.load();
Scene scene = new Scene(myPane);
Stage stage = new Stage();
stage.setResizable(false);
stage.setScene(scene);
FXMLTaskerController controler = new FXMLTaskerController();
controler.setUser(et_username.getText());
myLoader.setController(controler);
prevStage.close();
stage.show();
}else {
JOptionPane.showMessageDialog(null, "Usuario o ContraseƱa incorrecta");
}
}else if (link_login == event.getSource()){
System.out.println("Registrate!");
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Here's the other class controler, the one where i want my String.
public class FXMLTaskerController implements Initializable {
#FXML private ListView list_todo;
#FXML private ListView list_done;
#FXML public String username;
private void handleButtonAction(ActionEvent event) {
}
#Override
public void initialize(URL url, ResourceBundle rb) {
System.out.println(username);
list_todo.setCellFactory(new TaskCellFactory());
list_done.setCellFactory(new TaskCellFactory());
try {
getTasks();
} catch (IOException ex) {
Logger.getLogger(FXMLTaskerController.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void setUser(String username){
this.username = username;
}
public void getTasks() throws IOException{
Conector con = new Conector();
for(Task task: con.obtenerTareas("pepin")){
System.out.println(task);
if(task.isState()){
list_done.getItems().add(task);
}else{
list_todo.getItems().add(task);
}
}
}
}
And here are the fxml files:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane prefHeight="400.0" prefWidth="500.0" style="-fx-background-color: #0288D1; -fx-border-color: #01579B; -fx-border-width: 5;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="desktop_tasker.FXMLDocumentController">
<children>
<Label layoutX="215.0" layoutY="34.0" text="Sign In" textFill="WHITE">
<font>
<Font size="23.0" />
</font>
</Label>
<Hyperlink fx:id="link_login" layoutX="150.0" layoutY="269.0" onAction="#handleButtonAction" text="Not registered yet? Click here." textFill="WHITE" />
<TextField fx:id="et_username" layoutX="21.0" layoutY="102.0" prefHeight="25.0" prefWidth="425.0" promptText="Username" style="-fx-prompt-text-fill: #ffffff; -fx-background-color: #0288D1;" />
<Separator layoutX="27.0" layoutY="126.0" prefHeight="3.0" prefWidth="425.0" />
<Separator layoutX="27.0" layoutY="192.0" prefHeight="3.0" prefWidth="425.0" />
<Button fx:id="btn_signup" layoutX="27.0" layoutY="222.0" mnemonicParsing="false" onAction="#handleButtonAction" prefHeight="23.0" prefWidth="425.0" style="-fx-background-color: #FFA000; -fx-prompt-text-fill: #ffffff;" text="SignUp" textFill="WHITE" />
<PasswordField fx:id="et_password" layoutX="21.0" layoutY="167.0" prefHeight="25.0" prefWidth="425.0" promptText="Password" style="-fx-background-color: #0288D1; -fx-prompt-text-fill: #ffffff;" />
</children>
</AnchorPane>
And the other one:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="557.0" prefWidth="1012.0" style="-fx-background-color: #0288D1;" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="desktop_tasker.FXMLTaskerController">
<children>
<SplitPane dividerPositions="0.5811881188118811" layoutX="-8.0" layoutY="35.0" prefHeight="529.0" prefWidth="1027.0" style="-fx-background-color: #EEEEEE;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="28.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="list_todo" layoutY="-8.0" prefHeight="527.0" prefWidth="584.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<ListView fx:id="list_done" layoutY="14.0" prefHeight="527.0" prefWidth="420.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children></AnchorPane>
</items>
</SplitPane>
<MenuBar prefHeight="30.0" prefWidth="1012.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</AnchorPane>
As you can see I tried to use a controler and using a set pasing the String, the problem is that when I open the new scene, his controler resets and the String is no longer there, any idea why or how to solve this?
If you want to set a Controller with myLoader.setController(controler); you must do it before calling Pane myPane = (Pane)myLoader.load(); and also remove fx:controller="desktop_tasker.FXMLTaskerController" from FXMLTasker.fxml, else you get a LoadException: Controller value already specified.
See JavaDoc FXMLLoader.setController(Object controller):
Sets the controller associated with the root object. The value passed to this method is used as the value of the fx:controller attribute. This method must be called prior to loading the document when using controller event handlers when an fx:controller attribute is not specified in the document.
Alternatively you can request the Controller from FXMLLoader:
FXMLTaskerController controler = (FXMLTaskerController)myLoader.getController();
controler.setUser(et_username.getText());
But thereby you can't assume that username is set in initialize(URL url, ResourceBundle rb) and should removed from there.

ListView or ScrollPane scrollbars don't scroll

For a university project I have to create a GUI for an online version of a table game, the player can have some cards which I created by extending JavaFX ImageView and I want to put them inside the interface at runtime.
Therefore I inserted a JavaFX ListView inside a SplitPane but when I run my application the scroll bar doesn't work.
The cards are perfectly displayed and the scroll bar is visible, but when I try to use it, it just seems like a disabled button.
The same happens if I use a ScrollPane containing an HBox.
I tried to not use preferred sizes, I tried ScrollBarPolicies, nothing seems to work, in the end I came to the conclusion that the problem is somewhere inside the SplitPane.
I even thought maybe the JavaFX Application Thread stopped but when the scrollbar doesn't work it is actually running.
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<SplitPane fx:id="mainPlayerRootPane" disable="true" dividerPositions="0.10275689223057644" prefHeight="337.0" styleClass="mainPlayerRootPane" stylesheets="#style.css" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="client.view.GUI.MainPlayerPaneController">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<GridPane prefHeight="335.0" prefWidth="78.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="116.0" minHeight="10.0" prefHeight="80.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="118.0" minHeight="10.0" prefHeight="82.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="138.0" minHeight="10.0" prefHeight="86.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="85.0" minHeight="10.0" prefHeight="85.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Pane prefHeight="85.0" translateX="4.0">
<children>
<ImageView fitHeight="77.0" fitWidth="73.0" layoutX="5.0" layoutY="1.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../../../resources/images/VictoryPoints.png" />
</image>
</ImageView>
<Label fx:id="victoryPointsLabel" alignment="TOP_CENTER" contentDisplay="CENTER" opacity="0.9" prefHeight="79.0" prefWidth="70.0" text="99" textAlignment="JUSTIFY" textFill="WHITE">
<font>
<Font name="Trattatello" size="36.0" />
</font>
</Label>
</children>
</Pane>
<Pane prefHeight="85.0" translateX="4.0" GridPane.rowIndex="1">
<children>
<ImageView fitHeight="79.0" fitWidth="71.0" layoutY="4.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../../../resources/images/Coins.png" />
</image>
</ImageView>
<Label fx:id="coinsLabel" alignment="CENTER" contentDisplay="CENTER" opacity="0.9" prefHeight="82.0" prefWidth="77.0" text="20" textFill="#222020">
<font>
<Font name="Trattatello" size="30.0" />
</font>
</Label>
</children>
</Pane>
<Pane prefHeight="85.0" prefWidth="81.0" translateX="4.0" GridPane.rowIndex="2">
<children>
<ImageView fitHeight="79.0" fitWidth="73.0" layoutX="17.0" layoutY="2.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../../../resources/images/Servants.png" />
</image>
</ImageView>
<Label fx:id="servantsLabel" alignment="CENTER" contentDisplay="CENTER" opacity="0.9" prefHeight="101.0" prefWidth="70.0" text="10" textFill="#bcc600">
<font>
<Font name="Trattatello" size="24.0" />
</font>
</Label>
</children>
</Pane>
<Pane prefHeight="85.0" translateX="4.0" GridPane.rowIndex="3">
<children>
<ImageView fitHeight="79.0" fitWidth="71.0" layoutX="1.0" layoutY="3.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#../../../../resources/images/Emporiums.png" />
</image>
</ImageView>
<Label fx:id="emporiumsLabel" alignment="CENTER" contentDisplay="CENTER" layoutY="8.0" prefHeight="73.0" prefWidth="71.0" text="10">
<font>
<Font name="Trattatello" size="36.0" />
</font>
</Label>
</children>
</Pane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0">
<children>
<SplitPane dividerPositions="0.5345345345345346" orientation="VERTICAL" prefHeight="335.0" styleClass="mainPlayerRootPane" stylesheets="#style.css" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0">
<children>
<SplitPane dividerPositions="0.5" prefHeight="174.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0">
<children>
<ListView fx:id="cardsListView" editable="true" orientation="HORIZONTAL" prefHeight="172.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0">
<children>
<ListView fx:id="permitsListView" orientation="HORIZONTAL" prefHeight="172.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="134.0" prefWidth="710.0" />
</items>
</SplitPane>
</children>
</AnchorPane>
</items>
</SplitPane>
Its controller class:
package client.view.GUI;
import java.util.List;
import client.model_properties.PlayerProperty;
import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.SplitPane;
public class MainPlayerPaneController {
#FXML
private Label victoryPointsLabel;
#FXML
private Label coinsLabel;
#FXML
private Label servantsLabel;
#FXML
private Label emporiumsLabel;
#FXML
private SplitPane mainPlayerRootPane;
#FXML
private ListView<PoliticalCardView> cardsListView;
#FXML
private ListView<PoliticalCardView> permitsListView;
#FXML
private void initialize(){
}
public void initializeMainPlayerPane(PlayerProperty mainPlayer) {
this.victoryPointsLabel.textProperty().bind(mainPlayer.getVictoryPoint().asString());
this.coinsLabel.textProperty().bind(mainPlayer.getCoins().asString());
this.servantsLabel.textProperty().bind(mainPlayer.getnOfServants().asString());
this.emporiumsLabel.textProperty().bind(mainPlayer.getAvailableEmporiums().asString());
this.addToDeckView(mainPlayer.getDeck());
mainPlayer.getDeckProperty().addListener(new DeckListChangeListener());
}
private void addToDeckView(List<? extends String> cards) {
PoliticalCardView auxCard;
for(String n : cards) {
auxCard = new PoliticalCardView(n);
auxCard.initializeCardView();
this.cardsListView.getItems().add(auxCard);
}
}
private class DeckListChangeListener implements ListChangeListener<String> {
#Override
public void onChanged(javafx.collections.ListChangeListener.Change<? extends String> c) {
List<? extends String> added = c.getAddedSubList();
List<? extends String> removed = c.getRemoved();
for(String n : removed) {
Node toRemove = cardsListView.getItems().stream()
.filter( r -> ((PoliticalCardView) r).getColor().equals(n))
.findFirst()
.get();
cardsListView.getItems().remove(toRemove);
}
addToDeckView(added);
}
}
}
And the class i created to represent the cards.
package client.view.GUI;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import utility.UserInterfaceUtilities;
public class PoliticalCardView extends ImageView {
private Image cardImage;
private String color;
public PoliticalCardView(String color) {
this.color = color;
}
public void initializeCardView() {
this.cardImage = UserInterfaceUtilities.POLITICAL_COLORS_TO_IMAGES.get(this.color);
this.setImage(cardImage);
this.setFitHeight(150);
this.setFitWidth(100);
}
public String getColor() {
return this.color;
}
}
I would like to know where's the problem since in two days of research I haven't found nothing similar on the internet and also i used other scrollbars which work just fine.
The problem is here:
<SplitPane fx:id="mainPlayerRootPane" disable="true" ..... >
Your SplitPane is disabled.
When you disable a Node by setting its disabledProperty, all of its children become disabled.
Indicates whether or not this Node is disabled. A Node will become
disabled if disable is set to true on either itself or one of its
ancestors in the scene graph.
Remove disable="true" from the FXML declaration to avoid disabling your ListView or ScrollPane.

Key SPACE acts like focused button

Whenever SPACE key is pressed, it is registered and processed as a last pressed (focused) button. I cannot capture it as KeyEvent, and it acts as a button.
I want to generate and pass on char from buttons and keyboard keys pressed.
Here is the handler part of my code in the controller class:
public void handleKeys(KeyEvent key) {
char chr = key.getText().charAt(0);
handleSymbols(chr);
key.consume();
}
public void handleBtns(ActionEvent buttonPressed) {
char chr = buttonPressed.getSource().toString().toLowerCase().charAt(buttonPressed.getSource().toString().length() - 2);
handleSymbols(chr);
buttonPressed.consume();
}
Here is the FXML file beginning:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="container" prefHeight="500.0" prefWidth="400.0" style="-fx-background-color: #00e600"
stylesheets="/sample/main.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="sample.Controller"
onKeyPressed="#handleKeys">
<left>
<VBox prefHeight="300.0" prefWidth="50.0">
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</BorderPane.margin>
<Button onAction="#handleBtns" prefHeight="135.0" prefWidth="50" text="+">
<VBox.margin>
<Insets bottom="20.0" />
</VBox.margin>
</Button>
<Button onAction="#handleBtns" prefHeight="135.0" prefWidth="50" text="-" />
</VBox>
</left>
There is something similar here, but for SWING, so it does not work:Disabling space bar triggering click for JButton
How can i unbind SPACE as a default key for focused buttons? I just don't want SPACE to act as a button.
I added an eventFilter to the stage in the main class and it works
addEventFilter(KeyEvent.KEY_PRESSED, k -> {
if ( k.getCode() == KeyCode.SPACE){
k.consume();
}
});

Categories