I'm in the middle of a school project, but I'm stuck...
In Scene Builder there is an OnKeyPressed and an OnKeyReleased 'method', and when I assign my own method (See code further down) I want to check if I'm pressing the left or right arrow key.
The problem is, OnKeyReleased works fine, but the OnKeyPressed only works when I hold down shift!
Does anyone know the cause of this issue? and if so, how it can be fixed/worked around?
(I'm on a MacBook, could this have anything to do with it?)
Thanks :)
Method for OnKeyPressed:
#FXML
private void Input(KeyEvent e)
{
if(e.getCode().equals(KeyCode.LEFT))
{
System.out.println("Pressed left arrow key");
}
}
FullCode:
package seasweeper.seasweeper;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
public class SecondaryController implements Initializable {
#FXML
private Label Label_Character;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private void switchToPrimary() throws IOException
{
App.setRoot("primary");
}
#FXML
private void Input(KeyEvent e)
{
if(e.getCode().equals(KeyCode.LEFT))
{
System.out.println("Pressed left");
}
System.out.println("KeyCode: " + e.getCode());
}
}
FXML code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onKeyPressed="#moveLeft" onKeyReleased="#moveLeft" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seasweeper.seasweeper.PacificController">
<children>
<Button layoutX="422.0" layoutY="64.0" mnemonicParsing="false" onAction="#switchToPrimary" prefHeight="27.0" prefWidth="164.0" text="Switch to Primary" />
<Label layoutX="489.0" layoutY="31.0" text="Pacific" />
<Label fx:id="Label_Character" layoutX="273.0" layoutY="192.0" text="Character" />
</children>
</AnchorPane>
Other Scene Controller:
package seasweeper.seasweeper;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
public class PrimaryController {
#FXML
private Button Button_Arctic;
#FXML
private Button Button_Southern;
#FXML
private Button Button_Pacific;
#FXML
private Button Button_Atlantic;
#FXML
private Button Button_Indian;
#FXML
private Button Button_Pacific1;
#FXML
private void switchToPacific() throws IOException {
App.setRoot("pacific");
}
#FXML
private void switchToSouthern() throws IOException {
App.setRoot("southern");
}
#FXML
private void switchToAtlantic() throws IOException {
App.setRoot("atlantic");
}
#FXML
private void switchToIndian() throws IOException {
App.setRoot("indian");
}
#FXML
private void switchToArctic() throws IOException {
App.setRoot("arctic");
}
}
Other FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seasweeper.seasweeper.PrimaryController">
<children>
<Button fx:id="Button_Arctic" layoutX="226.0" layoutY="14.0" mnemonicParsing="false" onAction="#switchToArctic" prefHeight="77.0" prefWidth="148.0" text="Arctic" />
<Button fx:id="Button_Southern" layoutX="226.0" layoutY="309.0" mnemonicParsing="false" onAction="#switchToSouthern" prefHeight="77.0" prefWidth="148.0" text="Southern" />
<Button fx:id="Button_Pacific" layoutX="14.0" layoutY="162.0" mnemonicParsing="false" onAction="#switchToPacific" prefHeight="77.0" prefWidth="148.0" text="Pacific" />
<Button fx:id="Button_Atlantic" layoutX="226.0" layoutY="162.0" mnemonicParsing="false" onAction="#switchToAtlantic" prefHeight="77.0" prefWidth="148.0" text="Atlantic" />
<Button fx:id="Button_Indian" layoutX="438.0" layoutY="162.0" mnemonicParsing="false" onAction="#switchToIndian" prefHeight="77.0" prefWidth="148.0" text="Indian" />
<Button fx:id="Button_Shop" layoutX="556.0" layoutY="14.0" mnemonicParsing="false" prefHeight="30.0" prefWidth="30.0" text="\$" textFill="#009712" />
</children>
</AnchorPane>
On the same issue I changed OnKeyPressed from AnchorPane to some Button on that AnchorPane and OnKeyPressed works fine with arrows :)
#Override
public void initialize(URL location, ResourceBundle resources) {
someButton.addEventHandler(KeyEvent.KEY_PRESSED,
new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
switch (event.getCode().toString()) {
// your logic here
}
event.consume();
}
});
}
This one is a little tricky, but still relatively simple:
Node node = null;
node.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.KP_UP) { // KeyPressed_UP
// Do something
}
if (event.getCode() == KeyCode.KP_DOWN) { // KeyPressed_DOWN
// Do something
}
if (event.getCode() == KeyCode.KP_LEFT) { // KeyPressed_LEFT
// Do something
}
if (event.getCode() == KeyCode.KP_RIGHT) { // KeyPressed_RIGHT
// Do something
}
}
});
Remember to change "node" with your object (it could be a Scene, AnchorPane -or any kind of pane-, buttons, etc).
Related
I am working on a project that is going to involve adding panes (or hboxes if that works better) to a very wide HBox. I set it up in an fxml pretty easily but I'm already going to have to make a few of these and I would love to avoid all the copying pasting. So I figured I should try and use a for loop to populate the HBox but for whatever reason it is not working. I'm in the very beginning steps so my code is very simple and straight forward.
This is the basic sample I'm trying to recreate
<HBox>
<children>
<Pane fx:id="pane0" prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children></Pane>
<Pane fx:id="pane1" prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children></Pane>
<Pane fx:id="pane2" prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children></Pane>
</children>
</HBox>
So to create it dynamically (and for clarity) I created a class for the HBox and the panes. For now each pane just has a button but they will undergo further customization once this code works. Same with the HBox.
Here's the HBox
public class HBoxTestClass {
#FXML
HBox hBox = new HBox();
public HBoxTestClass(){
}
#FXML
public void initialize(){
populateHBox();
}
private void populateHBox(){
for (int i = 0; i < 3; i++){
hBox.getChildren().add(new TestPane());
hBox.setSpacing(10);
}
}
}
its fxml
<HBox fx:id="hBox" xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.HBoxTestClass"
prefHeight="400.0" prefWidth="600.0">
</HBox>
The pane class and its fxml
public class TestPane extends Pane{
#FXML Pane testPane = new Pane();
#FXML Button button = new Button();
public TestPane(){
}
#FXML
private void initialize(){
button.setText("Click Me!");
}
}
<Pane fx:id="testPane" xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="sample.TestPane"
prefHeight="200.0" prefWidth="200.0">
<children>
<Button fx:id="button" layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
</children>
</Pane>
So my very simple code above just produces a blank, wide screen with no panels in it. I put a console print in the constructor of my TestPane class so I know it's getting called but still nothing appears. Any advice? Thanks
I am not sure what you are doing in your code incorrectly. Code like #FXML Pane testPane = new Pane(); should look like #FXML Pane testPane;. I am not sure how code like #FXML
public void initialize(){ is being called in your program. Try to follow this MCVE.
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication363 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();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
Controller
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
#FXML
private HBox hBox;
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
for (int i = 0; i < 5; i++) {
StackPane stackPane = new StackPane(new Label("Label: " + i));
hBox.getChildren().add(stackPane);
}
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.HBox?>
<HBox fx:id="hBox" 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" fx:controller="javafxapplication363.FXMLDocumentController" />
I've seen bunch of posts connected with my problem but it seems like nothing works for me. I'm writing simple window app in Java FX and FXML. I have a Main class which has field with days names. I've got also two controller classes - Controller (which is like more important controller) and ShowDays. Each controller has their own FXML and they are responsible for switching scenes and working with user (and with Model = Main). In Controller class user can add a new day to our days names or remove last day. In ShowDays class user can print on window names of days. It's all connected with clicking buttons.
I know that I can organize my program easier and I can print names of days in Controller class and remove all ShowDays class but it's only a part of project I want to create and I just want to understand how real programmers would have done this kind of things.
This is my code:
public class Main extends Application {
private ArrayList<String> daysNames;
public Main() {
daysNames = new ArrayList<>();
}
public void addDay() {
String[] days = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
System.out.println("I'm adding day!" + daysNames.size());
if (getDaysNames().size() < 7)
getDaysNames().add(days[getDaysNames().size()]);
else
System.out.println("Can't add more days!");
}
public void removeDay() {
if (!getDaysNames().isEmpty())
getDaysNames().remove(getDaysNames().get(getDaysNames().size()-1));
}
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
//setters,getters...
}
Controller class:
public class Controller implements Initializable {
private Main myMain;
#FXML
private ShowDays showDays;
public Controller() {
myMain=new Main();
showDays = new ShowDays(myMain);
}
public Controller(Main main) {
this.myMain = main;
showDays = new ShowDays(myMain);
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void addDay() {
myMain.addDay();
}
public void removeDay() {
myMain.removeDay();
}
public void GOTOshowDays(ActionEvent event) throws IOException {
Parent showDaysParent = FXMLLoader.load(getClass().getResource("ShowDays.fxml"));
Scene showDaysScene = new Scene(showDaysParent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(showDaysScene);
window.show();
}
}
ShowDays class:
public class ShowDays implements Initializable {
#FXML
private Text text;
private Main myMain;
public ShowDays() {
myMain = new Main();
}
public ShowDays(Main main) {
myMain = main;
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
public void BackToController(ActionEvent event) throws IOException {
Parent controllerParent = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene controllerScene = new Scene(controllerParent);
Stage window = (Stage) ((Node)event.getSource()).getScene().getWindow();
window.setScene(controllerScene);
window.show();
}
public void showDaysInWindow(ActionEvent event) throws IOException {
String allText = "";
for (String day : myMain.getDaysNames())
allText += day + " ";
text.setText(allText);
}
}
and the FXML files:
sample.fxml
<HBox prefHeight="100.0" prefWidth="483.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Button layoutX="-8.0" layoutY="48.0" mnemonicParsing="false" onAction="#GOTOshowDays" text="GOTO show days" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<Button mnemonicParsing="false" onAction="#addDay" text="add day" />
<Button mnemonicParsing="false" onAction="#removeDay" text="remove day" />
ShowDays.fxml
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ShowDays">
<center>
<Text fx:id="text" strokeType="OUTSIDE" strokeWidth="0.0" BorderPane.alignment="CENTER" />
</center>
<top>
<Button mnemonicParsing="false" onAction="#showDaysInWindow" text="Show days" BorderPane.alignment="CENTER" />
</top>
<bottom>
<Button mnemonicParsing="false" onAction="#BackToController" text="Go back" BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>
I'm not sure if ShowDays user actions works as expected (it's all about that...) but Controller do. The problem is when I add a few days in Controller scene and then switch scene to ShowDays scene, it seems like I lose my Main instance... When I have one controller class, my code cope with working all time on the same instance of Main and adding/removing days works as expected but I can't cope with connecting multiple controllers to model and them each other... I've spend so much time trying to fix this and I don't really understand all of the tips which I found on the internet, so I ask you.
You should use Ideas from #James_D answer here. Your problem is how to pass a model from one Controller to the next. In this example, the model is a List<String>. The model is passed to the initial Controller named FXMLDocumentController. From that point, the model is passed between FXMLDocumentController and ShowDayscontroller. The showDaysInWindow method, shows the current model info in a Text node. addDay adds a day from the array days if the model is missing a day. removeDay removes a day from the model.
Main
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication320 extends Application
{
#Override
public void start(Stage stage)
{
try {
String[] days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
List<String> daysNames = new ArrayList();
for (int i = 0; i < days.length; i++) {
daysNames.add(days[i]);
}
//Load the FXML. Pass the model to initModel
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
fXMLDocumentController.initModel(daysNames);
Scene scene = new Scene(loader.getRoot());
stage.setScene(scene);
stage.show();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
FXMLDocumentController
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
List<String> model;
#FXML
private void goToShowDays(ActionEvent event)
{
try {
FXMLLoader showDaysLoader = new FXMLLoader(getClass().getResource("ShowDays.fxml"));
showDaysLoader.load();
ShowDaysController showDaysController = showDaysLoader.getController();
showDaysController.initModel(this.model);
Stage stage = (Stage) ((Button) event.getSource()).getScene().getWindow();
stage.setScene(new Scene(showDaysLoader.getRoot()));
}
catch (IOException ex) {
ex.printStackTrace();
}
}
#FXML
private void addDay(ActionEvent event)
{
String[] days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
List<String> tempDays = new ArrayList(Arrays.asList(days));
if (!this.model.containsAll(tempDays)) {
tempDays.removeAll(this.model);
if (tempDays.size() > 0) {
this.model.add(tempDays.get(0));
}
}
}
#FXML
private void removeDay(ActionEvent event)
{
if (this.model.size() > 0) {
Random random = new Random();
this.model.remove(random.nextInt(this.model.size()));
}
}
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
public void initModel(List<String> model)
{
// ensure model is only set once:
if (this.model != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.model = model;
this.model.forEach(System.out::println);
}
}
FXMLDocument
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<HBox prefHeight="100.0" prefWidth="483.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication320.FXMLDocumentController">
<children>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Button layoutX="-8.0" layoutY="48.0" mnemonicParsing="false" onAction="#goToShowDays" text="GOTO show days" />
</children>
</AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<Button mnemonicParsing="false" onAction="#addDay" text="add day" />
<Button mnemonicParsing="false" onAction="#removeDay" text="remove day" />
</children>
</HBox>
ShowDaysController
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.text.Text;
import javafx.stage.Stage;
/**
* FXML Controller class
*
* #author blj0011
*/
public class ShowDaysController implements Initializable
{
#FXML
Text text;
List<String> model;
#FXML
private void showDaysInWindow(ActionEvent event)
{
text.setText(String.join(" ", this.model));
}
#FXML
private void backToController(ActionEvent event)
{
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
fXMLDocumentController.initModel(this.model);
Stage stage = (Stage) ((Button) event.getSource()).getScene().getWindow();
stage.setScene(new Scene(loader.getRoot()));
}
catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* Initializes the controller class.
*
* #param url
* #param rb
*/
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
public void initModel(List<String> model)
{
// ensure model is only set once:
if (this.model != null) {
throw new IllegalStateException("Model can only be initialized once");
}
this.model = model;
this.model.forEach(System.out::println);
}
}
ShowDays FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication320.ShowDaysController">
<center>
<Text fx:id="text" strokeType="OUTSIDE" strokeWidth="0.0" BorderPane.alignment="CENTER" />
</center>
<top>
<Button mnemonicParsing="false" onAction="#showDaysInWindow" text="Show days" BorderPane.alignment="CENTER" />
</top>
<bottom>
<Button mnemonicParsing="false" onAction="#backToController" text="Go back" BorderPane.alignment="CENTER" />
</bottom>
</BorderPane>
I have a ListSelectionView (from the ControlsFX library) in JavaFX and I need it to display a set of values when a particular button is clicked. It displays the values when I place the add the contents into it in the initialize method. But when I place the same code in the event action method of a button it doesn't display. I have another method which gets the Source items and Target items from the ListSelectionView and displays them. Even though the ListSelectionView isn't displaying anything, the getSourceItems() method returns a set of values which are then displayed.
public class FXMLDocumentController implements Initializable {
#FXML
private Label label;
#FXML
private Button button;
#FXML
private JFXListView<Label> listv;
#FXML
private ListSelectionView<Label> abc;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
private void handleToggle(MouseEvent event) {
ObservableList<Label> users = FXCollections.observableArrayList();
abc.setSourceHeader(new Label("Present"));
abc.setTargetHeader(new Label("Absent"));
for (int i=0; i<4;i++)
{
users.add(new Label("Name "+i));
}
abc.setSourceItems(users);
abc.setDisable(false);
for (int i=0; i<4;i++)
{
Label k = new Label("Hello"+i);
listv.getItems().add(k);
}
}
#FXML
private void handlenewNOde(MouseEvent event) {
ObservableList<Label> users1 =abc.getSourceItems();
System.out.println("Source items");
for(int i =0; i<users1.size(); i++)
{
Label k=users1.get(i);
System.out.println(k.getText());
}
System.out.println("Target items");
ObservableList<Label> users12 =abc.getTargetItems();
for(int i =0; i<users12.size(); i++)
{
Label k=users12.get(i);
System.out.println(k.getText());
}
}
}
.fxml :
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXListView?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import org.controlsfx.control.ListSelectionView?>
<AnchorPane id="AnchorPane" prefHeight="680.0" prefWidth="914.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.141" fx:controller="listselectionviewtryout.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="14.0" layoutY="21.0" onAction="#handleButtonAction" text="Click Me!" />
<Label fx:id="label" layoutX="17.0" layoutY="54.0" minHeight="16" minWidth="69" />
<JFXListView fx:id="listv" layoutX="131.0" layoutY="35.0" prefHeight="237.0" prefWidth="75.0" />
<JFXButton layoutX="413.0" layoutY="58.0" onMouseClicked="#handleToggle" text="Toggle Extension" />
<JFXButton layoutX="445.0" layoutY="134.0" onMouseClicked="#handlenewNOde" text="new Node" />
<ListSelectionView fx:id="abc" layoutX="226.0" layoutY="262.0" />
</children>
</AnchorPane>
Ignore the JFXListView.
Output:
Source items
Name 0
Name 1
Name 2
Name 3
Target items
Should
abc.setSourceItems(users);
be
abc.getSourceItems().addAll(users);
I'm working on the project which contains multiple controllers (1 main and two for each of the Fxml files). Unfortunately while running the program, console throw the NullPointerExeption at me. I found out that it's the main controller fault, but still having this information I'm unable to fix this. Could you give me some tips how to solve this issue ?
Here i got the full track:
MainController class:
public class MainController {
#FXML LogInController logInController;
DBConnect dbConnect;
#FXML FlightControlController flightControlController;
#FXML public void initialize() {
logInController.initialize(this);
flightControlController.initialize(this);
dbConnect.initialize(this);
}
}
DBConnect class:
public void dbConnect() throws SQLException {
try {
Conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/nasa", "root", "1234");
} catch(Exception e) {
System.out.println(e.getStackTrace());
}
}
public boolean isCorrect(String login,String password) throws SQLException, IOException {
Stmt = Conn.createStatement();
Rs = Stmt.executeQuery("SELECT * FROM Users WHERE login='"+login+"'AND password='"+password+"';");
if(Rs.next()) {
return true;
} else {
return false;
}
}
public void initialize(MainController mainController) {
this.mainController=mainController;
}
LogInController class:
MainController mainController;
#FXML DBConnect dbConnect;
#FXML TextField logginField = null;
#FXML PasswordField passwordFiled=null;
#FXML Button logInButton;
#FXML
public void buttonClicked(ActionEvent event) throws SQLException, IOException {
mainController.dbConnect.dbConnect();
if(mainController.dbConnect.isCorrect(logginField.getText(),passwordFiled.getText())) {
Parent root = FXMLLoader.load(getClass().getResource("/view/FlightControlView.fxml"));
Scene scene = new Scene(root);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
} else {
System.out.print("An error have occured");
}
}
public void initialize(MainController mainController) {
this.mainController=mainController;
}
FlightControlController Class:
#FXML Label label;
MainController mainController;
public void initialize(MainController mainController) {
this.mainController = mainController;
}
And the error which occurs:
Caused by: java.lang.NullPointerException at
controller.LogInController.buttonClicked(LogInController.java:31) ...
62 more
I'm not sure but is it possible that MainController (which doesn't have his own Fxml file) so that FXMLLoader doesn't initialize MainController's properties?
#EDIT
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="693.0" prefWidth="1062.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.LogInController">
<children>
<SplitPane dividerPositions="0.21320754716981133" layoutX="331.0" layoutY="220.0" prefHeight="693.0" prefWidth="1062.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" prefWidth="100.0">
<children>
<Label alignment="CENTER" layoutY="-1.0" maxHeight="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="70.0" prefWidth="222.0" text="NASA DATABASE" />
<TextField fx:id="logginField" layoutX="18.0" layoutY="101.0" promptText="Login" />
<PasswordField fx:id="passwordFiled" layoutX="18.0" layoutY="165.0" promptText="Password" />
<Button fx:id="logInButton" onAction="#buttonClicked" layoutX="79.0" layoutY="230.0" mnemonicParsing="false" text="Log In" />
</children>
</AnchorPane>
<AnchorPane prefHeight="691.0" prefWidth="493.0" SplitPane.resizableWithParent="false">
<children>
<Label alignment="CENTER" layoutX="97.0" layoutY="104.0" prefHeight="417.0" prefWidth="635.0" text="NOT AVAILABLE, PLEASE LOG IN" AnchorPane.leftAnchor="113.0" AnchorPane.rightAnchor="113.0">
<font>
<Font name="System Bold Italic" size="37.0" />
</font>
</Label>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>
Is there a way to call the event handler method from the fxml file which holds parameter? please find the files:
My Fxml Looks like:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.cognizant.iotworkbench.View.AddImageController">
<children>
<Label layoutX="270.0" layoutY="14.0" text="Add Sensor" />
<BorderPane layoutY="-1.0" prefHeight="400.0" prefWidth="602.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<left>
<HBox fx:id="source" prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<ImageView fx:id="sourceimg" fitHeight="114.0" fitWidth="142.0" onDragDetected="#setUpGestureSource" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="file:Images/Project.png" />
</image>
</ImageView>
</children>
</HBox>
</left>
<right>
<HBox fx:id="target" onDragDropped="#setUpGestureTarget" onDragOver="#setUpGestureTarget" prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
</right>
</BorderPane>
</children>
</AnchorPane>
My controller class looks like
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
/**
* FXML Controller class
*
*/
public class AddImage implements Initializable,ControlledScreen {
ScreensController myController;
/**
* Initializes the controller class.
*/
#FXML
final HBox target=new HBox();
#FXML
final HBox source=new HBox();
#FXML
final ImageView sourceimg=new ImageView();
#FXML
public void setUpGestureSource()
{
System.out.println("source");
source.setOnDragDetected(new EventHandler <MouseEvent>() {
#Override
public void handle(MouseEvent event) {
/* drag was detected, start drag-and-drop gesture*/
System.out.println("onDragDetected");
/* allow MOVE transfer mode */
Dragboard db = source.startDragAndDrop(TransferMode.COPY);
/* put a string on dragboard */
ClipboardContent content = new ClipboardContent();
Image sourceImage = sourceimg.getImage();
content.putImage(sourceImage);
db.setContent(content);
event.consume();
}
});
}
#FXML
public void setUpGestureTarget(){
System.out.println("target");
target.setOnDragOver(new EventHandler <DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
if(db.hasImage()){
event.acceptTransferModes(TransferMode.COPY);
}
event.consume();
}
});
target.setOnDragDropped(new EventHandler <DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
if(db.hasImage()){
insertImage(db.getImage(), target);
event.setDropCompleted(true);
}else{
event.setDropCompleted(false);
}
event.consume();
}
});
}
void insertImage(Image i, HBox hb){
ImageView iv = new ImageView();
iv.setImage(i);
setUpGestureSource();
hb.getChildren().add(iv);
}
#Override
public void setScreenParent(ScreensController screenParent) {
myController=screenParent;
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
Drag and Drop event is not getting fired. I dont know what's wrong with the code. Please help
All methods that are annotated with #FXML may or may not have a parameter. If you need a parameter, you can directly pass the specific Event as a parameter to the method.
Let us take an example and say you have an onDragOver event added for a HBox in the fxml.
<HBox fx:id="targetBox" onDragOver="#setupGestureTarget">
...
</HBox>
Then you may have a method which does the needful inside the controller class.
#FXML
public void setupGestureTarget(DragEvent event) {
Dragboard db = event.getDragboard();
if(db.hasImage()){
event.acceptTransferModes(TransferMode.COPY);
}
event.consume();
}
If you need the source node for which the method was called, you can get an access to it by getSource() of the event, then type-caste it to Node.
public void setupGestureTarget(DragEvent event) {
...
((Node)event.getSource()).setId("myHbox");
System.out.println(targetBox.getId()); // Prints - myHbox
}
Note : For using methods specific to HBox, you can type-caste it to a HBox instead of a Node.
EDIT - As per user comments and updates
There are multiple issues with your approach. Let me address them all.
1.Values to the fields annotated with #FXML are injected while the FXML is getting loaded and should not carry new keyword.
#FXML
final HBox target=new HBox();
should be replaced by
#FXML
final HBox target;
2.As I have already stated your method can have a parameter which defines the Event. So the methods setUpGestureSource() and setUpGestureTarget() can be defined as :
#FXML
public void setUpGestureSource(DragEvent event) {
...
}
#FXML
public void setUpGestureTarget(DragEvent event) {
...
}
3.The method setUpGestureSource is called when a drag-event occurs on the ImageView, so you don't need to add another EventHandler for it.
#FXML
public void setUpGestureSource(MouseEvent event) {
/* drag was detected, start drag-and-drop gesture*/
System.out.println("onDragDetected");
* allow MOVE transfer mode */
Dragboard db = source.startDragAndDrop(TransferMode.COPY);
/* put a string on dragboard */
ClipboardContent content = new ClipboardContent();
Image sourceImage = sourceimg.getImage();
content.putImage(sourceImage);
db.setContent(content);
event.consume();
}
Similarly, change the other method as well.