This is what my view looks like:
Explanation
The entire window itself runs on one controller, called the CartWindowController, and the product list itself is a JavaFX Custom Control called CartItemComponent, which has it's own controller. Each item in the list, therefore has it's own instance of the controller as I programmatically make an instance and populate a VBox.
Problem
I cannot figure out how to notify the CartWindowController when the user clicks on the "X" button, which is handled by the "CartItemComponent" Controller. I would highly appreciate it if anyone could give me a heads up on how to tackle this problem.
Here's what my FXML looks like for the entire Window:
CartWindow.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane id="AnchorPane" fx:id="parent" prefHeight="400.0" prefWidth="600.0" styleClass="pane" stylesheets="#../assets/userwindow.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ordermanagementsystem.controllers.CartWindowController">
<children>
<Button layoutX="25.0" layoutY="25.0" mnemonicParsing="false" onAction="#exitWindow" prefHeight="35.0" prefWidth="20.0" styleClass="back-button" />
<Label layoutX="262.0" layoutY="17.0" styleClass="heading" text="Cart" />
<ScrollPane hbarPolicy="NEVER" layoutY="97.0" prefHeight="315.0" prefWidth="600.0" styleClass="no-padding">
<content>
<AnchorPane prefWidth="600.0" styleClass="no-padding">
<children>
<VBox fx:id="productList" layoutX="25.0" prefWidth="350.0" />
<AnchorPane layoutX="425.0" layoutY="25.0" prefWidth="150.0" styleClass="no-padding">
<children>
<Label layoutX="18.0" styleClass="heading-sub" text="Summary" />
<Label layoutX="1.0" layoutY="55.0" text="Gross:" />
<Label fx:id="grossTotal" alignment="CENTER_RIGHT" layoutX="47.0" layoutY="55.0" prefHeight="17.0" prefWidth="103.0" text="RM0.00" />
<Label layoutX="1.0" layoutY="75.0" text="Packaging:" />
<Label fx:id="packagingTotal" alignment="CENTER_RIGHT" layoutX="73.0" layoutY="75.0" prefHeight="17.0" prefWidth="77.0" text="RM0.00" />
<Label layoutX="1.0" layoutY="95.0" text="Total:" />
<Label fx:id="total" alignment="CENTER_RIGHT" layoutX="40.0" layoutY="95.0" prefHeight="17.0" prefWidth="110.0" styleClass="green-text" text="RM0.00" />
<Button layoutY="125.0" mnemonicParsing="false" onAction="#checkout" prefHeight="39.0" prefWidth="150.0" styleClass="action-button" text="Check Out" />
</children>
</AnchorPane>
</children>
</AnchorPane>
</content>
</ScrollPane>
</children>
</AnchorPane>
CartWindowController.java
package ordermanagementsystem.controllers;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import ordermanagementsystem.cart.CartState;
import ordermanagementsystem.orders.models.OrderItem;
import ordermanagementsystem.viewcomponents.CartItemComponent;
public class CartWindowController extends ViewController implements Initializable {
#FXML
public Parent parent;
#FXML
private VBox productList;
#FXML
private Label grossTotal;
#FXML
private Label packagingTotal;
#FXML
private Label total;
private CartState cartState;
#FXML
private void exitWindow(ActionEvent event) {
try {
this.openPage(this.parent, "MainWindow.fxml");
} catch (IOException ex) {
ex.printStackTrace();
}
}
#FXML
private void checkout(ActionEvent event) {
}
#Override
public void initialize(URL url, ResourceBundle rb) {
this.cartState = CartState.getInstance();
for (OrderItem item : this.cartState.getItems()) {
this.productList.getChildren().add(new CartItemComponent(item));
}
}
}
CartItemComponent.java:
package ordermanagementsystem.viewcomponents;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import ordermanagementsystem.DialogBox;
import ordermanagementsystem.cart.CartState;
import ordermanagementsystem.orders.models.OrderItem;
public class CartItemComponent extends AnchorPane {
#FXML
private AnchorPane frame;
#FXML
private TextField quantity;
#FXML
private Label total;
#FXML
private Label productName;
private OrderItem item;
private CartState cartState;
public CartItemComponent(OrderItem item) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/ordermanagementsystem/views/components/CartItemComponent.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
exception.getStackTrace();
}
this.cartState = CartState.getInstance();
this.item = item;
this.setQuantity(1);
this.quantity.setEditable(false);
this.productName.setText(this.item.getProduct().getName());
}
private void setQuantity(int quantity) {
this.quantity.setText(String.valueOf(quantity));
this.item.setQuantity(quantity);
this.cartState.updateItem(this.item);
this.total.setText("RM" + String.format("%.2f", item.getProduct().getPrice() * quantity));
}
private int getQuantity() {
return Integer.parseInt(this.quantity.getText());
}
private void updateSummary() {
}
#FXML
private void add(ActionEvent event) {
int quantity = this.getQuantity();
if (quantity == 99) {
DialogBox.showValidationDialog("The quantity cannot be over 99.");
} else {
this.setQuantity(quantity + 1);
}
}
#FXML
private void substract(ActionEvent event) {
int quantity = this.getQuantity();
if (quantity == 1) {
DialogBox.showValidationDialog("The quantity cannot be below 1.");
} else {
this.setQuantity(quantity - 1);
}
}
}
Something you could try is to pass the CartWindowController into the CartItemComponent constructor, then when you need to notify the CartWindowController, you call a method or set a flag or trigger an event, your choice! All you would need to do is add a parameter of type CartWindowController to you CartItemComponent and just save the reference.
Related
I'm creating a simple login GUI form using eclipse, JavaFX and scene builder. I've coded my program so that every time I click the login button, it would switch to another window but it doesn't work. i'm a beginner in java but we've been tasked to create a system in my class so I've only relied on youtube tutorials, any help would be appreciated!
this is my main code
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
my login form
package application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class Login {
#FXML
private Button button;
#FXML
private PasswordField password;
#FXML
private TextField username;
#FXML
private Label wrongLogin;
#FXML
public void Login(ActionEvent event) {
Stage primaryStage = new Stage();
if (username.getText().equals("admin") && password.getText().equals("admin")) {
try {
Parent root = FXMLLoader.load(getClass().getResource("BookRooms.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
my fxml file
<?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?>
<AnchorPane prefHeight="345.0" prefWidth="545.0" style="-fx-background-color: #fff2cc;" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Login">
<children>
<AnchorPane layoutX="132.0" layoutY="62.0" prefHeight="221.0" prefWidth="279.0" style="-fx-background-color: #545454; -fx-border-radius: 10;">
<children>
<Label layoutX="34.0" layoutY="60.0" prefHeight="25.0" prefWidth="56.0" text="Username:" textFill="WHITE" />
<Label layoutX="34.0" layoutY="98.0" prefHeight="25.0" prefWidth="56.0" text="Password:" textFill="WHITE" />
<TextField layoutX="106.0" layoutY="60.0" promptText="Enter Username ID:" />
<TextField layoutX="106.0" layoutY="98.0" promptText="Enter Password" />
<Button alignment="CENTER" layoutX="106.0" layoutY="137.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="73.0" style="-fx-background-color: #fff2cc;" text="LOGIN" />
</children></AnchorPane>
<Label layoutX="225.0" layoutY="36.0" text="HOTEL DEL LUNA" />
</children>
</AnchorPane>
Your button in fxml can't call Login() in its controller class because there is no onAction attribute in fxml button tag .
So ,in <Button alignment="CENTER" layoutX="106.0" layoutY="137.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="73.0" style="-fx-background-color: #fff2cc;" text="LOGIN" /> add onAction="#Login" inside Button Tag:
<Button alignment="CENTER" layoutX="106.0" layoutY="137.0" mnemonicParsing="false" onAction="#Login" prefHeight="25.0" prefWidth="73.0" style="-fx-background-color: #fff2cc;" text="LOGIN" />
And , naming a method in a class with exact the same name of that class is concidered a bad practice. Only constructors must match its name with class identifier
I have a TableView with a single Column and I want to have a Button in the last row of that TableView/Column. The Button should be disabled until a row is selected and then it should be enabled. I've done numerous searches on this but everything I've found seems to be adding a button to every row within a multi-column table. Is there a quick way to do this?
Here are some sample images:
TableButtonView.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?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.layout.VBox?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="406.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tablebutton.TableButtonController">
<children>
<VBox layoutX="60.0" layoutY="22.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label alignment="CENTER" maxWidth="1.7976931348623157E308" prefHeight="51.0" prefWidth="200.0" text="Agency Customization">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="40.0">
<children>
<Label alignment="CENTER_RIGHT" maxHeight="1.7976931348623157E308" prefHeight="30.0" prefWidth="70.0" text="Agency: " />
<TextField fx:id="agencyTextField" maxHeight="1.7976931348623157E308" prefHeight="30.0" prefWidth="45.0" />
<Button fx:id="addButton" maxHeight="1.7976931348623157E308" onAction="#onAdd" prefHeight="30.0" prefWidth="67.0" text="_Add">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Button>
</children>
<padding>
<Insets bottom="10.0" />
</padding>
</HBox>
<TableView fx:id="agencyTableView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="276.0">
<columns>
<TableColumn fx:id="agencyColumn" prefWidth="188.0" text="Agency" />
</columns>
<VBox.margin>
<Insets left="5.0" right="5.0" />
</VBox.margin>
</TableView>
<ButtonBar maxWidth="1.7976931348623157E308">
<buttons>
<Button fx:id="okAgencyButton" mnemonicParsing="false" onAction="#onOK" text="OK" />
<Button fx:id="cancelAgencyButton" mnemonicParsing="false" onAction="#onCancel" text="Cancel" />
</buttons>
<padding>
<Insets bottom="5.0" right="20.0" top="5.0" />
</padding>
</ButtonBar>
</children>
</VBox>
</children>
</AnchorPane>
TableButtonController.java:
package tablebutton;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class TableButtonController implements Initializable {
private WebView helpWebView;
#FXML
private TextField agencyTextField;
#FXML
private Button addButton;
#FXML
private TableView<String> agencyTableView;
#FXML
private TableColumn<String, String> agencyColumn;
#FXML
private Button okAgencyButton;
#FXML
private Button cancelAgencyButton;
#Override
public void initialize(URL url, ResourceBundle rb) {
agencyColumn.setCellValueFactory(cellData ->
new ReadOnlyStringWrapper(cellData.getValue())
);
agencyColumn.setStyle( "-fx-alignment: CENTER;");
ObservableList<String> agencies = FXCollections.observableArrayList(
"AA","DL","LH");
agencyTableView.getItems().addAll(agencies);
}
#FXML
private void onAdd(ActionEvent event) {
}
#FXML
private void onOK(ActionEvent event) {
// Just exit for now
Stage stage = (Stage) okAgencyButton.getScene().getWindow();
stage.close();
}
#FXML
private void onCancel(ActionEvent event) {
// Just exit for now
Stage stage = (Stage) cancelAgencyButton.getScene().getWindow();
stage.close();
}
}
TableButton.java:
package tablebutton;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class TableButton extends Application {
#Override
public void start(Stage primaryStage) {
try
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("TableButtonView.fxml"));
Scene scene = new Scene((Parent) loader.load());
primaryStage.setScene(scene);
primaryStage.setTitle("TableView Button Test");
primaryStage.show();
}
catch (IOException ignored)
{
}
}
public static void main(String[] args) {
launch(args);
}
}
Trying to put the button actually inside the TableView is problematic and not recommended. There is a technical difficulty in getting the button to render in the last row of the TableView (this is not trivial), and there are also potential usability issues (what if there are a lot of rows in the table and the table needs to be scrolled, does the remove button just scroll out of view? if so, then how would a user find it if they wanted to remove something).
Instead, don't put the button in the TableView:
Use a VBox which contains the the TableView and the Button.
Set appropriate constraints so that the Button butts right up under the TableView and is sized to the width of the TableView.
Bind the disable property of the Button to an empty selected items set.
Sample code:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Remover extends Application {
#Override
public void start(Stage stage) throws Exception {
ObservableList<NamedColor> colors = FXCollections.observableArrayList(
new NamedColor("red", Color.RED),
new NamedColor("green", Color.GREEN),
new NamedColor("blue", Color.BLUE),
new NamedColor("indigo", Color.INDIGO)
);
TableView<NamedColor> table = new TableView<>(colors);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
TableColumn<NamedColor, String> colorNames = new TableColumn<>("Colors");
colorNames.setCellValueFactory(new PropertyValueFactory<>("name"));
table.getColumns().add(colorNames);
Button remove = new Button("Remove");
remove.disableProperty().bind(
Bindings.isEmpty(
table.getSelectionModel().getSelectedItems()
)
);
remove.setMaxWidth(Double.MAX_VALUE);
remove.setOnAction(event ->
table.getItems()
.removeAll(
table.getSelectionModel().getSelectedItems()
)
);
VBox layout = new VBox(table, remove);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(Remover.class);
}
public static class NamedColor {
private String name;
private Color color;
public NamedColor(String name, Color color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public Color getColor() {
return color;
}
}
}
I am unable to change the text of my label from other class.
I need to constantly update date and time on the main screen, while I may be able to perform other functions too, simultaneously.
I have used a TimeSetting class, which extends Thread and in it's run() method, I've called the updation command in an infinite loop, using setText() and then slept the method for a second.
But on running this, nothing happens and on closing the output window, I get an error saying NullPointerExcpetion
Here's the code for the two classes :
FXMLDocumentController.java
package crt;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class FXMLDocumentController extends Thread implements Initializable
{
#FXML
protected Label check;
#FXML
**protected Label date;**
#FXML
protected Label time;
#FXML
protected Label RRRR;
#FXML
protected Label DDDD;
#FXML
protected Label SSSS;
#FXML
protected Label temp;
#FXML
protected Label maxtemp;
#FXML
protected Label mintemp;
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
//dc.setDate(date.textProperty().bind(valueproperty));
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
Parent root1 = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
stage.setTitle("MENU");
stage.setScene(new Scene(root1));
stage.show();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Text?>
<AnchorPane id="AnchorPane" prefHeight="367.0" prefWidth="510.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="crt.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="387.0" layoutY="302.0" minHeight="25.0" minWidth="80.0" onAction="#handleButtonAction" onTouchPressed="#handleButtonAction" text="Menu" />
<Label fx:id="date" layoutX="56.0" layoutY="64.0" minHeight="25.0" minWidth="80.0" />
<Label fx:id="time" layoutX="361.0" layoutY="64.0" minHeight="25.0" minWidth="80.0" text="S" />
<Label fx:id="RRRR" layoutX="76.0" layoutY="100.0" minHeight="25.0" minWidth="70.0" />
<Label fx:id="DDDD" layoutX="195.0" layoutY="100.0" minHeight="25.0" minWidth="70.0" />
<Label fx:id="SSSS" layoutX="314.0" layoutY="100.0" minHeight="25.0" minWidth="70.0" />
<Text layoutX="136.0" layoutY="163.0" strokeType="OUTSIDE" strokeWidth="0.0" text="TEMP :-" />
<Label fx:id="temp" layoutX="275.0" layoutY="156.0" minHeight="25.0" minWidth="70.0" text="A" />
<Text layoutX="136.0" layoutY="203.0" strokeType="OUTSIDE" strokeWidth="0.0" text="MAX TEMP :-" />
<Label fx:id="maxtemp" layoutX="275.0" layoutY="188.0" minHeight="25.0" minWidth="70.0" text="B" />
<Text layoutX="136.0" layoutY="243.0" strokeType="OUTSIDE" strokeWidth="0.0" text="MIN TEMP :-" />
<Label fx:id="maxtemp" layoutX="275.0" layoutY="225.0" minHeight="25.0" minWidth="70.0" text="C" />
<ProgressBar layoutX="401.0" layoutY="21.0" prefHeight="18.0" prefWidth="70.0" progress="0.0" />
<Button fx:id="startbutton" layoutX="14.0" layoutY="18.0" mnemonicParsing="false" onAction="#startstart" text="START" />
<Label fx:id="check" layoutX="42.0" layoutY="306.0" />
</children>
</AnchorPane>
TimeSetting.java
package crt;
import java.util.Date;
public class TimeSetting extends Thread {
#Override
public void run()
{
FXMLDocumentController fdc = new FXMLDocumentController();
// fdc.load();
int i=0;
while(true)
{
Date d = new Date();
fdc.date.setText("fd" + i);
i++;
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
}
}
}
}
CRT.java
package crt;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class CRT extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) throws InterruptedException {
launch(args);
TimeSetting ts = new TimeSetting();
ts.start();
}
}
launch() does not complete until the Application exits. You should start the thread in the start method of your application.
Furthermore new FXMLDocumentController() obviously creates a new instance of the controller class - one that isn't connected to any fxml, so none of the fields is injected. More info about communicating with a controller can be found here: Passing Parameters JavaFX FXML
Also if you get this to work, you're still using a thread different to the JavaFX application thread to modify the UI. This should not be done. Instead use Platform.runLater to update the UI:
while(true) {
Date d = new Date();
final String text = "fd" + i;
Platform.runLater(() -> {
fdc.date.setText(text);
});
i++;
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
}
}
Hello stackoverflowers,
I have a question "I have an fxml file "CrawlerView.fxml" and its controller "CrawlerController.java" and a main Application class I want to send Message(database insert) from controller class to main Application class(because i cant do business logic in GUI/fxml controller class) . So my question is: Is it possible to send message from fxml controller class to main application class"
code is below
any help
thanx in advance`
Crawler.java
package app.model.main;
import java.io.IOException;
import java.sql.Statement;
import java.util.Stack;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Crawler extends Application {
private Stage MStage;
private BorderPane rootLayout;
#FXML Button SEARCH;
#FXML TextField URL;
static Conection conection;
static url_entries URLS;//self implemented classes
static word_count count;//self implemented classes
static Statement stmt;
//static public Stack DATABASE;
public static void test(){}
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage MStage)
{
try {
FXMLLoader RootLoader = new FXMLLoader();
FXMLLoader CrawlerLoader = new FXMLLoader();
RootLoader.setLocation(Crawler.class.getResource("view/RootView.fxml"));
CrawlerLoader.setLocation(Crawler.class.getResource("view/CrawlerView.fxml"));
rootLayout = (BorderPane) RootLoader.load();
AnchorPane CV = (AnchorPane) CrawlerLoader.load();
rootLayout.setCenter(CV);
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
MStage.setScene(scene);
MStage.show();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
CrawlerView.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="628.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.model.main.CrawlerController">
<children>
<SplitPane dividerPositions="0.14424635332252836" layoutX="8.0" layoutY="-2.0" orientation="VERTICAL" prefHeight="628.0" prefWidth="600.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="100.0" prefWidth="160.0">
<children>
<Label layoutX="105.0" layoutY="14.0" prefHeight="52.0" prefWidth="388.0" text="Khurasani Web Crawler" textFill="#792323">
<font>
<Font name="Bauhaus 93" size="34.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TextField id="URL" fx:id="URL" alignment="CENTER" blendMode="DARKEN" layoutX="110.0" layoutY="25.0" prefHeight="34.0" prefWidth="359.0" text="Enter URL">
<font>
<Font name="Berlin Sans FB Demi Bold" size="17.0" />
</font>
<effect>
<InnerShadow choke="0.56" color="#722424" height="26.93" radius="12.965" width="26.93" />
</effect>
</TextField>
<Button id="SEARCH" fx:id="SEARCH" layoutX="247.0" layoutY="82.0" mnemonicParsing="false" prefHeight="27.0" prefWidth="79.0" text="Search" textFill="#5e2929">
<font>
<Font name="Arial Black" size="15.0" />
</font>
</Button>
</children>
</AnchorPane>
</items>
</SplitPane>
CrawlerController
package app.model.main;
import java.net.URL;
import java.sql.Statement;
import java.util.ResourceBundle;
import java.util.Stack;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
public class CrawlerController implements Initializable
{
#FXML Button SEARCH;
#FXML TextField URL;
#Override // This method is called by the FXMLLoader when initialization is complete
public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
assert SEARCH != null : "fx:id=\"myButton\" was not injected: check your FXML file 'simple.fxml'.";
SEARCH.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event)
{
//How to send message to main application class
}
});}
}
I'm trying to make a program to Log in or register a person. But I am getting the Exception.(InvocationTargetException and the NullPointerException)
Error Stack Trace
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:363)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:303)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:875)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$147(LauncherImpl.java:157)
at com.sun.javafx.application.LauncherImpl$$Lambda$48/1099983479.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at gui.StartSchermController.<init>(StartSchermController.java:81)
at StartUp.start(StartUp.java:27)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821)
at com.sun.javafx.application.LauncherImpl$$Lambda$51/93724165.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323)
at com.sun.javafx.application.PlatformImpl$$Lambda$45/128893786.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/2063964656.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291)
at com.sun.javafx.application.PlatformImpl$$Lambda$46/1108411398.run(Unknown Source)
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.lambda$null$141(WinApplication.java:102)
at com.sun.glass.ui.win.WinApplication$$Lambda$37/1147985808.run(Unknown Source)
... 1 more
Exception running application StartUp
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)
I have problem with this line.
chTaal.setItems(FXCollections.observableArrayList(dc.keuzeTaal()));
StartSchermController.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package gui;
import domein.DomeinController;
import java.io.IOException;
import java.util.ArrayList;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
/**
* FXML Controller class
*
* #author Eigenaar
*/
public class StartSchermController extends SplitPane {
#FXML
private TextField txfMeldID;
#FXML
private TextField txfMeldWw;
#FXML
private TextField txfRegNaam;
#FXML
private TextField txfRegVNaam;
#FXML
private TextField txfRegWw2;
#FXML
private TextField txfRegWw;
#FXML
private TextField txfRegID;
#FXML
private Label lblMeldAan;
#FXML
private Label lblRegistreer;
#FXML
private Label lblMeldId;
#FXML
private Label lblMeldWw;
#FXML
private Label lblRegNaam,lblRegVNaam,lblRegId,lblRegWw,lblRegWw2;
#FXML
private Button btnMeldAan,btnRegistreer;
private final DomeinController dc;
#FXML
private ComboBox cmbTaal;
#FXML
private TextField txfStartExc;
/**
* Initializes the controller class.
* #param dc
*/
public StartSchermController(DomeinController dc) {
this.dc=dc;
FXMLLoader loader=new FXMLLoader(getClass().getResource("StartScherm.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
cmbTaal.setItems(FXCollections.observableArrayList(dc.keuzeTaal()));
}
public int geefKeuze(){
int s = cmbTaal.getSelectionModel().getSelectedIndex();
return s;
}
#FXML
private void cmbTaalOnAction(ActionEvent event) {
int keuzeTaal = cmbTaal.getSelectionModel().getSelectedIndex();
System.out.println(keuzeTaal);
updateTaal(dc.setTaal(keuzeTaal));
this.geefKeuze();
}
private void updateTaal(ArrayList<String> s) {
lblMeldAan.setText(s.get(0));
this.lblMeldId.setText(s.get(1));
this.lblMeldWw.setText(s.get(2));
this.lblRegistreer.setText(s.get(3));
this.lblRegNaam.setText(s.get(4));
this.lblRegVNaam.setText(s.get(5));
this.lblRegId.setText(s.get(6));
this.lblRegWw.setText(s.get(7));
this.lblRegWw2.setText(s.get(8));
}
#FXML
private void btnMeldAanOnAction(ActionEvent event){
String id= this.txfMeldID.getText();
String ww= this.txfMeldWw.getText();
try{
dc.meldAan(id, ww);
}catch(Exception e){
txfStartExc.setText(e.getMessage());
this.txfMeldID.setText("");
this.txfMeldWw.setText("");
}
this.txfMeldID.setText("");
this.txfMeldWw.setText("");
}
#FXML
private void btnRegistreerOnAction(ActionEvent event){
String n=this.txfRegNaam.getText();
String vn=this.txfRegVNaam.getText();
String id= this.txfRegID.getText();
String ww= this.txfRegWw.getText();
String ww2=this.txfRegWw2.getText();
dc.maakSpelerAan(n, vn, id, ww);
}
}
this is the code from my fxml file generated by JavaFX Scene Builder 2.0
StartScherm.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<fx:root dividerPositions="0.17839195979899497" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" orientation="VERTICAL" prefHeight="400.0" prefWidth="600.0" type="SplitPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gui.StartSchermController">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<Label layoutX="352.0" text="SOKOBAN" textFill="#d7300f">
<font>
<Font name="Colonna MT" size="48.0" />
</font>
</Label>
<ComboBox fx:id="cmbTaal" layoutX="46.0" layoutY="18.0" onAction="#cmbTaalOnAction" prefWidth="150.0" />
</children></AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="257.0" prefWidth="598.0">
<children>
<SplitPane dividerPositions="0.481421647819063" layoutY="-8.0" prefHeight="400.0" prefWidth="621.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="346.0" prefWidth="295.0">
<children>
<Label fx:id="lblMeldAan" layoutX="12.0" layoutY="1.0" prefHeight="27.0" prefWidth="106.0">
<font>
<Font size="18.0" />
</font>
</Label>
<Label fx:id="lblMeldId" layoutX="14.0" layoutY="42.0" prefHeight="17.0" prefWidth="74.0" />
<TextField fx:id="txfMeldID" layoutX="97.0" layoutY="38.0" />
<Label fx:id="lblMeldWw" layoutX="14.0" layoutY="83.0" prefHeight="17.0" prefWidth="74.0" />
<TextField fx:id="txfMeldWw" layoutX="97.0" layoutY="79.0" />
<TextField fx:id="txfStartExc" layoutX="26.0" layoutY="184.0" prefHeight="116.0" prefWidth="244.0" />
<Button fx:id="btnMeldAan" layoutX="97.0" layoutY="129.0" mnemonicParsing="false" onAction="#btnMeldAanOnAction" text="Meld aan" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Label fx:id="lblRegistreer" layoutX="14.0" layoutY="1.0" prefHeight="27.0" prefWidth="106.0">
<font>
<Font size="18.0" />
</font>
</Label>
<Label fx:id="lblRegNaam" layoutX="8.0" layoutY="41.0" prefHeight="17.0" prefWidth="113.0" text="" />
<Label fx:id="lblRegWw" layoutX="8.0" layoutY="148.0" prefHeight="17.0" prefWidth="113.0" text="" />
<Label fx:id="lblRegId" layoutX="8.0" layoutY="112.0" prefHeight="17.0" prefWidth="113.0" text="" />
<Label fx:id="lblRegVNaam" layoutX="8.0" layoutY="76.0" prefHeight="17.0" prefWidth="113.0" text="" />
<Label fx:id="lblRegWw2" layoutX="8.0" layoutY="185.0" text="" />
<TextField fx:id="txfRegNaam" layoutX="128.0" layoutY="37.0" />
<TextField fx:id="txfRegVNaam" layoutX="128.0" layoutY="72.0" />
<TextField fx:id="txfRegWw2" layoutX="128.0" layoutY="181.0" />
<TextField fx:id="txfRegWw" layoutX="128.0" layoutY="144.0" />
<TextField fx:id="txfRegID" layoutX="128.0" layoutY="108.0" />
<Button fx:id="btnRegistreer" layoutX="128.0" layoutY="226.0" mnemonicParsing="false" onAction="#btnRegistreerOnAction" text="Registreer" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children></AnchorPane>
</items>
</fx:root>
DomeinController.java
package domein;
import java.util.ArrayList;
import java.util.Locale;
import java.util.ResourceBundle;
public class DomeinController {
private final SpelerRepository spelerRepository;
private Speler speler;
// private Spel spel;
public DomeinController() {
spelerRepository = new SpelerRepository();
}
/*
public void registreer(String naam, String voornaam, String email, LocalDate geboortedatum, String wachtwoord, String wachtwoordBevestiging) {
if (!wachtwoord.equals(wachtwoordBevestiging)) {
throw new EmailException();
}*/
/*
Speler nieuweSpeler = new Speler(naam, voornaam, gebruikersID, wachtwoord);
setSpeler(nieuweSpeler); // ONTBREEKT!!
spelerRepository.voegToe(nieuweSpeler);
}*/
/** UC_1 meldAan DOING */
public void meldAan(String gebruikersID, String wachtwoord) {
Speler gevondenSpeler = spelerRepository.meldAan(gebruikersID, wachtwoord);
if (gevondenSpeler != null) {
setSpeler(gevondenSpeler);
}
}
/** UC_1 meldAan KNOWING */
public String[] geefDetailsSpeler() {
return speler.geefDetailsSpeler();
/* if (speler == null) {
return null;
}
String[] spelerS = new String[3];
spelerS[0] = speler.getVoornaam();
spelerS[1] = speler.getNaam();
return spelerS;*/
}
private void setSpeler(Speler speler){
this.speler = speler;
}
public void maakSpelerAan(String naam, String voornaam, String gebruikersID, String wachtwoord) {
Speler s=new Speler(naam,voornaam,gebruikersID,wachtwoord,false);
spelerRepository.voegToe(s);
}
public ArrayList<String> keuzeTaal(){
ArrayList<String> taal = new ArrayList<>();
taal.add("Nederlands");
taal.add("Français");
taal.add("English");
return taal;
}
public ArrayList<String> setTaal(int i){
ResourceBundle taal=setResourceBundle(i);
ArrayList<String> s= new ArrayList<>();
s.add(taal.getString("meldAan"));
s.add(taal.getString("userID"));
s.add(taal.getString("wachtwoord"));
s.add(taal.getString("registreer"));
s.add(taal.getString("naam"));
s.add(taal.getString("voornaam"));
s.add(taal.getString("userID"));
s.add(taal.getString("wachtwoord"));
s.add(taal.getString("herhalingWachtwoord"));
return s;
}
public static ResourceBundle setResourceBundle(int taalKeuze) {
Locale locale=null;
ResourceBundle taal;
if (taalKeuze==1) {
locale = Locale.FRENCH;
} else if (taalKeuze==2) {
locale = Locale.ENGLISH;
} else if(taalKeuze==0) {
locale = new Locale("nl");
}
return ResourceBundle.getBundle("taal\\LabelsBundle", locale);
}
;
}
/*
private void setSpel(Spel spel) {
this.spel = spel;
}
*/
Main Class StartUp.java
import domein.DomeinController;
import gui.StartSchermController;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.stage.Stage;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Eigenaar
*/
#SuppressWarnings("unchecked")
public class StartUp extends Application
{
#Override
#SuppressWarnings("unchecked")
public void start(Stage stage)
{
DomeinController controller = new DomeinController();
StartSchermController root = new StartSchermController(controller);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Startscherm Sokoban");
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
Thank you in advance. I hope somebody can help me.
I don't think your FXML is loading. Add a System.exit(1); to the catch block after you call loader.load(); to check.
If you use loader.setController(...), you should not have a fx:controller attribute in the FXML file. Remove that attribute, and it should fix the problem.