On Mouse Entered Method to swap Button position - javafx

I would like to develop a mouse entered method that swaps the locations of two buttons in real time using FXML and JavaFX which I am unfortunately very new to. Relocate(x,y), get/setLayoutX/Y and below get/setTranslateX/Y all throw IllegalArgumentEceptions with not much more understandable information in the stack trace. What is the preferred Button Property to use in order to get and then set a real-time location swap?
#FXML protected void neinHover (ActionEvent evt){
double jTmpX, jTmpY, nTmpX, nTmpY;
nTmpX = neinButton.getTranslateX();
nTmpY = neinButton.getTranslateY();
jTmpX = jaButton.getTranslateX();
jTmpY = jaButton.getTranslateY();
jaButton.setTranslateX(nTmpX);
jaButton.setTranslateY(nTmpY);
neinButton.setTranslateX(jTmpX);
neinButton.setTranslateY(jTmpY);
}

I supose you want something like this:
FXML:
<fx:root onMouseClicked="#swap" type="Pane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<Button fx:id="b1" mnemonicParsing="false" text="1" />
<Button fx:id="b2" layoutX="90.0" mnemonicParsing="false" text="2" />
</children>
</fx:root>
Controller:
public class MockPane extends Pane {
#FXML
private Button b1;
#FXML
private Button b2;
public MockPane() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"MockPane.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#FXML
private void swap() {
double b1x = b1.getLayoutX();
double b1y = b1.getLayoutY();
double b2x = b2.getLayoutX();
double b2y = b2.getLayoutY();
b1.setLayoutX(b2x);
b1.setLayoutY(b2y);
b2.setLayoutX(b1x);
b2.setLayoutY(b1y);
}
}
App:
public class MockApp extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) throws Exception {
MockPane root = new MockPane();
Scene scene = new Scene(root, 200, 100);
stage.setScene(scene);
stage.show();
}
}

Related

issue with using extended JavaFX Class Dialog<R> and initializing the DialogPane

I use an extended Dialog class in my JavaFX application, but I failed to initialize the fields of the DialogPane. It seems the initialize method is never invoked. I make several modifications of the program code, unfortunately I do not have success. Therefore I hope you can help me. Thanks!
The application is reduced to a minimum: the main program starts via ControllerFactory the PortalController. There is a button to open my 'DialogFriZi'. The related DialogPane contains a label. The initializing of this label failed.
main program:
public class Main extends Application {
private final Logger logger = Logger.getLogger(this.getClass().getName());
private final String FXML_PORTAL = "portal.fxml";
private MyHandler myHandler = new MyHandler();
#Override
public void init() {
try{
// Thread.currentThread is the FX-Launcher thread:
Thread.currentThread().setUncaughtExceptionHandler(myHandler);
try {
logger.addHandler(new FileHandler("java.myLOG"));
}
catch (IOException e) {
throw new IllegalStateException("IOException when adding File Handler");
}
}
catch (Exception ex) {
myHandler.uncaughtException(Thread.currentThread(), ex);
throw(ex);
}
}
#Override
public void start(Stage primaryStage) {
try{
logger.info("Test Application started");
Thread.currentThread().setUncaughtExceptionHandler(myHandler);
try{
URL location = new URL(this.getClass().getResource("resources/fxml/" + FXML_PORTAL).toString());
FXMLLoader loader = new FXMLLoader(location);
loader.setControllerFactory(new SimpleControllerFactory(primaryStage));
Pane root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setTitle("*** TEST App ***");
primaryStage.show();
}
catch(IOException ex) {
ex.printStackTrace();
throw new IllegalStateException("check program source code!");
}
}
catch(Exception ex) {
myHandler.uncaughtException(Thread.currentThread(), ex);
throw(ex);
}
}
public static void main(String[] args) {
launch(args);
}
class MyHandler implements Thread.UncaughtExceptionHandler{
#Override
public void uncaughtException(Thread thread, Throwable throwable) {
logger.log(Level.SEVERE, "** STOPP ** due to uncaught exception", throwable);
Platform.exit();
}
}
}
ControllerFactory
public class SimpleControllerFactory implements Callback<Class<?>,Object> {
private static final Logger logger = Logger.getLogger(SimpleControllerFactory.class.getName());
private final Stage primaryStage;
// types of controller
public SimpleControllerFactory(Stage stage) {
this.primaryStage = stage;
}
public SimpleControllerFactory() { this(null); }
#Override
public Object call(Class<?> type) {
try {
for (var c : type.getConstructors()) {
switch(c.getParameterCount()) {
case 0 -> { }
case 1 -> {
if ( c.getParameterTypes()[0] == Stage.class) {
return c.newInstance(primaryStage) ;
}
else;
}
default -> { }
}
}
return type.getDeclaredConstructor().newInstance();
}
catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException ex) {
logger.log(Level.SEVERE,ex.toString(),ex);
throw new RuntimeException(ex);
}
}
}
PortalController
public class PortalController implements Initializable {
private static final Logger logger = Logger.getLogger(PortalController.class.getName());
private final Stage recentStage;
private ResourceBundle resourceBundle;
public PortalController(Stage stage) {
this.recentStage = stage;
}
public PortalController() {
this(null);
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
#FXML
private void start(ActionEvent event) {
DialogFriZi dialog = null;
dialog = new DialogFriZi(recentStage);
Optional<Boolean> result = dialog.showAndWait();
}
}
related FXML file
<VBox prefHeight="500.0" prefWidth="400.0" spacing="5.0" style="-fx-padding: 5 5 5 5;-fx-font-size: 11px" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="TestSimpleDialog.PortalController">
<children>
<HBox alignment="CENTER">
<children>
<Button mnemonicParsing="false" onAction="#start" text="start FriZi dialog">
<HBox.margin>
<Insets top="50.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</children>
the extended Dialog class
public class DialogFriZi extends Dialog<Boolean> {
#FXML private ButtonType okButtonType;
#FXML Label label;
private static final Logger logger = Logger.getLogger(DialogFriZi.class.getName());
private final Stage recentStage;
public DialogFriZi(Stage primaryStage) {
this.recentStage = primaryStage;
runDialog();
}
public DialogFriZi() {
this(null);
}
#FXML private void initialize() {
System.out.println("start initializing");
label.setText("hello");
}
private void runDialog() {
FXMLLoader loader = new FXMLLoader();
try {
loader.setLocation(new URL
(this.getClass().getResource("resources/fxml/dialogFriZi.fxml").toString()));
DialogPane dialogPane = loader.load();
loader.setController(this);
initOwner(recentStage);
initModality(Modality.APPLICATION_MODAL);
setResizable(true);
setTitle("FriZi Dialog");
setDialogPane(dialogPane);
}
catch (IOException e) {
String message = "illegale state due to problem with 'resource dialogFriZi.fxml'";
logger.log(Level.SEVERE,message);
throw new IllegalStateException(message);
}
}
}
related FXML file
<DialogPane prefHeight="400.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1">
<content>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<Label fx:id="label" text="Label" />
</children></HBox>
</content>
<buttonTypes>
<ButtonType buttonData="OK_DONE" text="ok" />
<ButtonType buttonData="CANCEL_CLOSE" text="Abbrechen" />
</buttonTypes>
The initalize() method is invoked on the controller, if there is one, during the execution of the load() method. You are setting the controller after calling load(), so when load() runs, there is no controller. You need to change the order of the calls:
private void runDialog() {
FXMLLoader loader = new FXMLLoader();
try {
loader.setLocation(new URL
(this.getClass().getResource("resources/fxml/dialogFriZi.fxml").toString()));
loader.setController(this);
DialogPane dialogPane = loader.load();
// loader.setController(this);
initOwner(recentStage);
initModality(Modality.APPLICATION_MODAL);
setResizable(true);
setTitle("FriZi Dialog");
setDialogPane(dialogPane);
}
catch (IOException e) {
String message = "illegale state due to problem with 'resource dialogFriZi.fxml'";
logger.log(Level.SEVERE,message);
throw new IllegalStateException(message);
}
}

JavaFX fx:id doesn´t create a Object in the controller class

Hello I am new to JavaFX and have problems with the fx:id.
I get a null pointer exception in my controller class.
The objects apple and snake are not created, although the fx:id and declarations in the controller class match.
Can someone help me?
Main-Class:
public class Main extends Application {
private Controller controll = new Controller();
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("World2.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
scene.setOnKeyPressed(controll);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Controller-Class:
public class Controller implements EventHandler<Event> {
#FXML
private ImageView snake;
#FXML
private ImageView apple;
private int snakeRow = 8;
private int snakeColumn = 10;
private int appleRow = 5;
private int appleColumn = 5;
#Override
public void handle(Event ev) {
KeyEvent event = (KeyEvent) ev;
System.out.println("handle-Methode");
if (event.getCode() == KeyCode.LEFT && snakeColumn > 0) {
snakeColumn--;
System.out.println("Snake-ID: " + snake);
System.out.println("Apple-ID: " + apple);
}
}
FXML:
<ImageView fx:id="apple" fitHeight="39.0" fitWidth="44.0" pickOnBounds="true" GridPane.columnIndex="5" GridPane.rowIndex="5">
<image>
<Image url="#../img/icons8-apfel-48.png" />
</image>
</ImageView>
<ImageView fx:id="snake" fitHeight="36.0" fitWidth="44.0" pickOnBounds="true" GridPane.columnIndex="10" GridPane.rowIndex="8">
<image>
<Image url="#../img/icons8-hydra-48.png" />
</image>
</ImageView>
A controller instance is not associated with a scene unless
It's created by FXMLLoader based on the fx:controller attribute in the fxml. In this case you'd need to retrieve the controller instance from the FXMLLoader instance used to load the fxml after loading:
FXMLLoader loader = new FXMLLoader(getClass().getResource("World2.fxml"));
Parent root = loader.load();
Controller controll = loader.getController();
or
You don't specify the fx:controller attribute but pass a Object to FXMLLoader before loading that is to be used as controller for the scene:
FXMLLoader loader = new FXMLLoader(getClass().getResource("World2.fxml"));
loader.setController(controll);
Parent root = loader.load();

How to add a javafx shortcut key combinations for buttons

My UI has a adding button and I want to assign a keyboard shortcut combination for that. I have failed to use the setAcceleartor for this purpose.
What is the easiest way to set up keyboard shortcuts in javafx applications?
button declaration in the UI:
<Button fx:id="addButton" alignment="CENTER" minWidth="-Infinity" mnemonicParsing="false" onAction="#addAction" prefHeight="31.0" prefWidth="130.0" text="Add" HBox.hgrow="ALWAYS" />
Controller button binding:
#FXML
private Button addButton;
The method that wants to setOnAction for the shortcut for the button:
public void addAction(ActionEvent event) throws SQLException, ClassNotFoundException {
if (validateInput()) {
String productName = productField.getText();
double unitPrice = Double.parseDouble(priceField.getText());
int quantity = Integer.parseInt(quantityField.getText());
double total = unitPrice * quantity;
ITEMLIST.add(new Item(productName, unitPrice, quantity, total));
calculation();
resetAdd();
productTableView.getSelectionModel().clearSelection();
ObservableList<Product> productsData = ProductDAO.searchProducts();
populateProducts(productsData);
searchField.setText("");
}
}
initialize() method:
#FXML
private void initialize() throws SQLException, ClassNotFoundException, IOException {
setSaveAccelerator(addButton);
}
The code I tried with setAccelerator:
private void setSaveAccelerator(final Button button) {
Scene scene = button.getScene();
if (scene == null) {
throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene");
}
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN),
new Runnable() {
#FXML public void run() {
button.fire();
}
}
);
}
In your setSaveAccelerator method, instead of directly calling addAction(ActionEvent event), just instruct the button to fire its event to its listeners such as: button.fire(). For example:
private void setSaveAccelerator(Button button) {
if(button==null) {
System.out.println("Button is null! "); // check that the button was injected properly through your fxml
}
Scene scene = button.getScene();
if (scene == null) {
throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene");
}
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN),
new Runnable() {
#FXML public void run() {
button.fire();
}
}
);
}
EDIT
To also avoid the IllegalArgumentException you must attach the accelerator after the button is attached to a scene. I managed to achieve this by creating a public method in the controller to attach the accelerator after the scene has been set. Then, in the class where the scene is loaded the controller's method can be called which sets up this functionality. See the example below:
In the controller class (in my case MainController):
public void setup() {
setSaveAccelerator(button);
}
In your main class when loading the fxml file:
FXMLLoader loader = new FXMLLoader(MainController.class.getResource("mainFXML.fxml"));
AnchorPane page = (AnchorPane) loader.load();
MainController controller = loader.getController();
Scene scene = new Scene(page);
controller.setup(); // calls the setup method attaching the accelerators
FULL EXAMPLE
Main class:
public class Main extends Application{
public static Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception {
Main.primaryStage=primaryStage;
FXMLLoader loader = new FXMLLoader(MainController.class.getResource("mainFXML.fxml"));
AnchorPane page = (AnchorPane) loader.load();
MainController controller = loader.getController();
Scene scene = new Scene(page);
primaryStage.setTitle("Shortcut example");
primaryStage.setScene(scene);
controller.setup();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Maincontroller:
public class MainController {
#FXML
private ResourceBundle resources;
#FXML
private URL location;
#FXML
private Button button;
#FXML
private AnchorPane rootPane;
#FXML
private TextArea textarea;
#FXML
void action(ActionEvent event) {
textarea.setText("Action fired!!");
}
#FXML
void initialize() {
assert button != null : "fx:id=\"button\" was not injected: check your FXML file 'MainFXML.fxml'.";
assert rootPane != null : "fx:id=\"rootPane\" was not injected: check your FXML file 'MainFXML.fxml'.";
assert textarea != null : "fx:id=\"textarea\" was not injected: check your FXML file 'MainFXML.fxml'.";
}
public void setup() {
setSaveAccelerator(button);
}
private void setSaveAccelerator(Button button) {
if(button==null) {
System.out.println("Button null!!");
}
Scene scene = button.getScene();
if (scene == null) {
throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene");
}
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN),
new Runnable() {
#FXML public void run() {
button.fire();
}
}
);
}
}
MainFXML.fxml
<AnchorPane fx:id="rootPane" prefHeight="408.0" prefWidth="330.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<Button fx:id="button" layoutX="139.0" layoutY="350.0" mnemonicParsing="false" onAction="#action" text="Button" />
<TextArea fx:id="textarea" layoutX="73.0" layoutY="38.0" prefHeight="200.0" prefWidth="200.0" />
</children>
</AnchorPane>

JavaFX milti-windows exception

I've found such a problem:
Having a MainWindow and 2 SubWindows, but I've got exceptions like:
-Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
-Caused by: java.lang.NullPointerException: Location is required.
-[...]
-at ApplicationForTests.SubWin1.SubWin1.display(SubWin1.java:14)
> Parent root = FXMLLoader.load(getClass().getResource("ApplicationForTests/SubWin1UI.fxml"));
-[...]
-at ApplicationForTests.MainController.openSub1(MainController.java:22)
> subWin1.display();
-[...]
-Exception in thread "Thread-3" java.lang.IncompatibleClassChangeError
Main:
public class Main extends Application {
public static BdcsDAO db = new BdcsDAO();
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("MainUI.fxml"));
primaryStage.setTitle("Main window");
primaryStage.setScene(new Scene(root, 500, 400));
primaryStage.show();
db.connect();
}
public static void main(String[] args) {launch(args);}
MainController:
public class MainController {
#FXML
Button button1;
#FXML
Button button2;
#FXML
public void openSub1() {
SubWin1 subWin1 = new SubWin1();
try {
subWin1.display();
} catch (IOException e) {
e.printStackTrace();
}
}
#FXML
public void openSub2() {
SubWin2 subWin2 = new SubWin2();
try {
subWin2.display();
} catch (IOException e) {
e.printStackTrace();
}
}
}
MainUI:
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ApplicationForTests.MainController">
<children>
<Button fx:id="button1" onAction="#openSub1" layoutX="268.0" layoutY="185.0" mnemonicParsing="false" text="SubWin1" />
<Button fx:id="button2" onAction="#openSub2" layoutX="268.0" layoutY="285.0" mnemonicParsing="false" text="SubWin2" />
</children>
</AnchorPane>
SubWin1:
public class SubWin1 {
public void display() throws IOException {
Stage window = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("ApplicationForTests/SubWin1UI.fxml"));
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle("Sub window no. 1");
window.setScene(new Scene(root, 800, 500));
window.show();
}
}
SubWin1Controller:
public class SubWin1Controller {
#FXML
Button button;
#FXML
public void loadTableView() throws SQLException {
setAlarmsTableView(Main.db.getSampleResultSet());
}
#FXML
private TableView<AlarmType> alarmsTableView;
#FXML
private TableColumn<?, ?> columnDeviceIndex;
#FXML
private TableColumn<?, ?> columnAlgorithmType;
private ObservableList<AlarmType> dataAlarms = FXCollections.observableArrayList();
public void setAlarmsTableView(ResultSet rs) throws SQLException {
columnDeviceIndex.setCellValueFactory(new PropertyValueFactory<>("deviceIndex"));
columnAlgorithmType.setCellValueFactory(new PropertyValueFactory<>("algorithmType"));
while (rs.next()) {
dataAlarms.add(new AlarmType(rs.getInt(1), rs.getInt(2));
}
alarmsTableView.setItems(dataAlarms);
}
}

Java FXML Add ObservableList to TableView

I can't display my Observable List in the table view. I don't get any error. I was check if Observable List and List have value and everything looks fine. I don't have any idea where is a problem. I was try to add ValueFactory also in FXML code and it still don't work
FXML
<TableView fx:id="laczenie" layoutX="641.0" layoutY="52.0" prefHeight="415.0" prefWidth="438.0">
<columns>
<TableColumn prefWidth="75.0" text="Wezly" fx:id="C1" >
</TableColumn>
<TableColumn prefWidth="361.0" text="MozliwePolaczenia" fx:id="C2">
</TableColumn>
</columns>
</TableView>
JavaFx Controller
public class FXMLDocumentController implements Initializable {
private JavaFXApplication4 mainApp;
public List<Krawendzie> list = new ArrayList<Krawendzie>();
#FXML
private TableColumn C1;
#FXML
private TableColumn C2;
#FXML
private TableView<Krawendzie> laczenie;
#FXML
private Label label;
#FXML
private ComboBox<String> combo;
#FXML
private GridPane Scena;
#FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
C1.setCellValueFactory(new PropertyValueFactory<Krawendzie,Integer>("Wezel"));
C2.setCellValueFactory(new PropertyValueFactory<Krawendzie,Integer>("Mozliwosci"));
combo.getItems().addAll("2","3","4","5","6","7","8");
list.removeAll(list);
}
#FXML
private void itemselected(ActionEvent event){
}
#FXML
private void rysuj(ActionEvent event) {
rysuj2(Integer.parseInt(combo.getValue()));
}
private void rysuj2(Integer Ilosc){
list.removeAll(list);
Scena.getChildren().clear();
laczenie = new TableView<Krawendzie>();
File f = new File("././Image/Imapges1.jpg");
Image image = new Image(f.toURI().toString());
Integer ilosc = 0;
for (int i = 0; i<=Ilosc;i++)
{
for(int k = 1;k<Scena.getColumnConstraints().size();k=k+2)
{
if(k%2 != 0)
{
Circle circle = new Circle(20, 20, 20);
circle.setFill(new ImagePattern(image));
Scena.add(circle,k,i);
list.add(new Krawendzie(ilosc,ilosc));
ilosc++;
}
if(ilosc == Ilosc)
break;
}
if(ilosc == Ilosc)
break;
}
getData();
}
public void getData()
{
ObservableList<Krawendzie> obsList = FXCollections.observableArrayList(list);
laczenie.setItems(obsList);
//return obsList;
}
}
And Main Application
public class JavaFXApplication4 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);
}
}
sorry for question i have an answer. I only need to delete
laczenie = new TableView();
because i was create a new object of talbeview so i can't work

Resources