Setting menu items css font style has no visible effect - css

I would like to change the MenuItem's text to bold when the user clicks on it. To manage to do this I'm using setStyle, but unfortunately it has no visible effect. The css makes no effect when the user selects the MenuItem option. The css styling only has an effect in initialize method.
I created a minimal reproducible example for the problem:
MAIN:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public final class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml"));
Scene scene = new Scene(root, 850.0, 650.0);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MAIN FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane prefHeight="475.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="MainController">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu fx:id="menu" mnemonicParsing="false" text="Switch Chart">
<items>
<MenuItem text="MenuItem1" />
<MenuItem onAction="#setFontBold" text="MenuItem2" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
MAIN CONTROLLER:
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
public class MainController implements Initializable {
#FXML private Menu menu;
private List<MenuItem> menuItems;
#Override
public void initialize(URL location, ResourceBundle resources) {
menuItems = menu.getItems();
menuItems.get(0).setStyle("-fx-font-weight: bold");
}
public void setFontBold() {
menuItems.get(1).setStyle("-fx-font-weight: bold");
System.out.println(menuItems.get(1).getStyle());
System.out.println("Font set to bold in menuitem with index 1 has no effect...");
}
}
So I get the following css effects, even after selecting the first indexed menu item (so onAction=#setFontBold not changes anything visually).
No bold effect. - only if you set the style in initialize()
I'm curious about why it makes no difference? It definitely sets the style to bold, but it is displayed as a regular font even after changing it to bold.
EDIT: JavaFX version: 8.0.211-b10

If I would have to stick to javafx 8 and switching was the requirement, I would have used RadioMenuItem. It does the job as expected, but does not make MenuItem text bold.
From official docs, I found following excerpt that would be useful.
ToggleGroup toggleGroup = new ToggleGroup();
RadioMenuItem radioItem1 = new RadioMenuItem("Option 1");
radioItem.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
System.out.println("radio toggled");
}
});
radioItem1.setToggleGroup(toggleGroup);
RadioMenuItem radioItem2 = new RadioMenuItem("Option 2");
radioItem.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
System.out.println("radio toggled");
}
});
radioItem2.setToggleGroup(toggleGroup);

Related

How to create a scrollpane on fxml using controller

I would like to create a scrollpane and button from the controller and display it in fxml, is that possible? This my code but it doesn't work
controller
package application;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
public class controller {
ScrollPane scrollPane = new ScrollPane();
Button button = new Button("My Button");
public void initialize() {
button.setPrefSize(400, 300);
scrollPane.setContent(button);
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
}
}
main
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final Parent parent = FXMLLoader.load(getClass().getResource("ui.fxml"));
primaryStage.setTitle("ScrollPane Demo ");
primaryStage.setScene(new Scene(parent,600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);}
}
fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<VBox id="vbox" prefHeight="400" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller">
<children>
<Pane prefHeight="200.0" prefWidth="200.0" />
</children>
</VBox>
You need to include your vbox in your controller, like this:
#FXML
private VBox vbox;
After that, add your scrollpane to your vbox's children:
vbox.getChildren().add(scrollPane);
Note that, you not added your button to your scrollpane's content, so your scrollpane is currently empty!
Edit: why you want to add nodes via fxml and from code too? Use this solution if it is really necessary, anyway use fxml to build your UI.

JavafX - Dynamic ImageView Set Default Size

I have an ImageView which I have configured so that it is resized to fit its parent AnchorPane with the two following lines of code (both the AnchorPane and the image are square).
preview.fitWidthProperty().bind(previewPane.maxWidthProperty());
preview.fitHeightProperty().bind(previewPane.maxWidthProperty());
I have also set a fitWidth of 450 px in an fxml file that injects all nodes. When I create an instance of this object however it opens the preview with a width equal to that of the loaded image (2000 px) and not 450 px. The resizing functionality works as expected and it is possible to shrink it down to 450 px. I was wondering however if it is possible to make sure it opens up with a default size different from that of the width of the image but also making sure so that it grows and shrinks with its parent.
I have tried setting loads of different default widths in both java code and fxml but the only thing that seems to work is unbinding the fitWidth which I don't want.
Do you have any suggestions as to how I might solve this?
Main:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class MainTest extends Application {
#FXML private AnchorPane previewPane;
#FXML private ImageView preview;
#Override
public void start(Stage primaryStage) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Test.fxml"));
fxmlLoader.setController(this);
fxmlLoader.setClassLoader(getClass().getClassLoader());
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
preview.fitWidthProperty().bind(previewPane.maxWidthProperty());
preview.fitHeightProperty().bind(previewPane.maxWidthProperty());
Scene scene = new Scene(previewPane);
primaryStage.setTitle("Test");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="previewPane" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fx:id="preview" fitHeight="450.0" fitWidth="450.0" layoutX="55.0" layoutY="36.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<image>
<Image url="#Blue%20Eyes%20White%20Dragon.png" />
</image>
</ImageView>
</children>
</AnchorPane>
EDIT: Here is a MCVE of my problem.
The structure of your project is wrong. Also, to fix the problem you are having, you need to set the Scene size.
Code to get the ImageView from the Controller
//Code in the Main
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
ImageView preView = fXMLDocumentController.getPreview();
//Code in the Controller
public ImageView getPreview()
{
return preview;
}
Code to set the Scene's size
stage.setWidth(450);
stage.setHeight(450);
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication213 extends Application
{
#Override
public void start(Stage stage) throws Exception
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
Parent root = loader.load();
FXMLDocumentController fXMLDocumentController = loader.getController();
ImageView preView = fXMLDocumentController.getPreview();
Scene scene = new Scene(root);
stage.setWidth(450);
stage.setHeight(450);
stage.setScene(scene);
stage.show();
preView.fitHeightProperty().bind(stage.heightProperty());
preView.fitWidthProperty().bind(stage.widthProperty());
}
/**
* #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.image.ImageView;
/**
*
* #author blj0011
*/
public class FXMLDocumentController implements Initializable
{
#FXML
private ImageView preview;
#Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
public ImageView getPreview()
{
return preview;
}
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="previewPane" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication213.FXMLDocumentController">
<children>
<ImageView fx:id="preview" fitHeight="450.0" fitWidth="450.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<image>
<Image url="#Blue%20Eyes%20White%20Dragon.png" />
</image>
</ImageView>
</children>
</AnchorPane>
Finally, you need to uncheck Preserve Ratio. The FXML should already have this unchecked. I am pointing this out because it's important.

JAVAFX ListView chatting

I need to insert values in list view in one by one like chatting.
now my code is
#FXML
private ListView<String> messageList;
private ObservableList<String> messages = FXCollections.observableArrayList();
messageList.setItems(messages);
This may be similar to what you are asking.
Main:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ChatApp 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.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
public class FXMLDocumentController implements Initializable {
#FXML private ListView lvChatWindow;
#FXML private TextField tfUser1, tfUser2;
ObservableList<String> chatMessages = FXCollections.observableArrayList();//create observablelist for listview
//Method use to handle button press that submits the 1st user's text to the listview.
#FXML
private void handleUser1SubmitMessage(ActionEvent event) {
chatMessages.add("User 1: " + tfUser1.getText());//get 1st user's text from his/her textfield and add message to observablelist
tfUser1.setText("");//clear 1st user's textfield
}
//Method use to handle button press that submits the 2nd user's text to the listview.
#FXML
private void handleUser2SubmitMessage(ActionEvent event) {
chatMessages.add("User 2: " + tfUser2.getText());//get 2nd user's text from his/her textfield and add message to observablelist
tfUser2.setText("");//clear 2nd user's textfield
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
lvChatWindow.setItems(chatMessages);//attach the observablelist to the listview
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="349.0" prefWidth="549.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.60" fx:controller="chatapp.FXMLDocumentController">
<children>
<Button fx:id="bntUser1Send" layoutX="99.0" layoutY="299.0" onAction="#handleUser1SubmitMessage" text="send message user1" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
<Button fx:id="btnUser2Send" layoutX="351.0" layoutY="299.0" mnemonicParsing="false" onAction="#handleUser2SubmitMessage" text="send message user2" />
<ListView fx:id="lvChatWindow" layoutX="75.0" layoutY="29.0" prefHeight="200.0" prefWidth="419.0" />
<TextField fx:id="tfUser1" layoutX="36.0" layoutY="258.0" prefHeight="25.0" prefWidth="239.0" />
<TextField fx:id="tfUser2" layoutX="293.0" layoutY="258.0" prefHeight="25.0" prefWidth="239.0" />
</children>
</AnchorPane>
This app simulates two different users sending messages to one listview. Similar to a chat. More comments in Controller

Why doesn't my Spinner update its bound property the first time it is initialized?

I have a Spinner in controller:
#FXML
private Spinner<Integer> spnMySpinner;
and a SimpleIntegerPropertyin controller:
private static final SimpleIntegerProperty myValue =
new SimpleIntegerProperty(3); //load a default value
I have bound them together in controller's initialize method:
spnMySpinner.getValueFactory().valueProperty().bindBidirectional(myValueProperty().asObject());
But the bindings work correctly only after second time the controller initializes. Here's how I can reproduce it:
I open the stage with the associated controller, it loads the default value, specified in the myValue property correctly (a number 3).
I click the increment button on the spinner to make it a 4. It changes the value in the spinner's value property, but the bound property myValue is left intact with the number 3.
I close the stage/window.
I reopen it, the spinner has again a value of 3.
I increment it again. Boom now the binding works and I have a "4" both inside the spinner and the bound property.
Entire minimalistic, but launchable/reproducible code:
Main.java:
package spinnerpoc;
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 Main extends Application {
#Override
public void start(Stage stage) throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("MainWindow.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MainWindow.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="myRoot" id="AnchorPane" prefHeight="231.0" prefWidth="337.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.60" fx:controller="spinnerpoc.MainWindowController">
<children>
<Button fx:id="btnOpenSpinnerWindow" layoutX="102.0" layoutY="103.0" mnemonicParsing="false" text="Open SpinnerWindow" onAction="#onOpenSpinnerWindow"/>
</children>
</AnchorPane>
MainWindowController.java:
package spinnerpoc;
import java.io.IOException;
import java.net.URL;
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.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class MainWindowController implements Initializable {
#FXML
private Button btnOpenSpinnerWindow;
#FXML
private AnchorPane myRoot;
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
private void onOpenSpinnerWindow(ActionEvent event) throws IOException{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("SpinnerWindow.fxml"));
Parent root = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.initOwner(myRoot.getScene().getWindow());
stage.initModality(Modality.WINDOW_MODAL);
stage.setTitle("SpinnerWindow");
stage.setScene(new Scene(root));
stage.show();
}
}
SpinnerWindow.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.SpinnerValueFactory.DoubleSpinnerValueFactory?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<ScrollPane xmlns:fx="http://javafx.com/fxml/1" fitToWidth="true" prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.60" fx:controller="spinnerpoc.SpinnerWindowController">
<content>
<VBox maxWidth="1.7976931348623157E308">
<children>
<Spinner fx:id="spnMySpinner" editable="true" prefWidth="50.0" max="10" min="1" />
</children>
</VBox>
</content>
</ScrollPane>
SpinnerWindowController.java:
package spinnerpoc;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Spinner;
public class SpinnerWindowController implements Initializable {
private static final SimpleIntegerProperty myValue = new SimpleIntegerProperty(3);
public static SimpleIntegerProperty myValueProperty() {
return myValue;
}
public static Integer getMyValue() {
return myValue.getValue();
}
public static void setMyValue(int value) {
myValue.set(value);
}
#FXML
private Spinner<Integer> spnMySpinner;
#Override
public void initialize(URL url, ResourceBundle rb) {
spnMySpinner.getValueFactory().valueProperty().bindBidirectional(myValueProperty().asObject());
}
}
(Code also available at a BitBucket repo.)
What am I missing?
You are running into the "premature garbage collection" problem. See a description of this here. You will likely find that it's not always every other time you show the spinner that it fails, but is just sporadic, and that the behavior will vary from one machine to another. If you limit the memory available to the JVM, you might find that it never works.
When you call IntegerProperty.asObject(), it
Creates an ObjectProperty that bidirectionally bound to this IntegerProperty.
Now note that a bidirectional binding has this feature to prevent accidental memory leaks:
JavaFX bidirectional binding implementation use weak listeners. This means bidirectional binding does not prevent properties from being garbage collected.
So the bidirectional binding you explicitly create does not prevent the thing it is bound to (the ObjectProperty<Integer> created by asObject()) from being garbage collected. Since you keep no references to it, it is eligible for garbage collections as soon as you exit the initialize() method in the SpinnerWindow Controller. Obviously, once the value to which your spinner value is bidirectionally bound is garbage collected, the binding will not work any more.
Just for demonstration purposes, you can see this by putting in a hook to force garbage collection. E.g. do
<ScrollPane onMouseClicked="#gc" xmlns:fx="http://javafx.com/fxml/1" ...>
in SpinnerWindow.fxml and
#FXML
private void gc() {
System.out.println("Invoking GC");
System.gc();
}
in SpinnerWindowController. If you do this, then clicking in the scroll pane will force garbage collection, and changing the spinner value will not update the property.
To fix this, retain a reference to the property you get from asObject():
public class SpinnerWindowController implements Initializable {
private static final SimpleIntegerProperty myValue = new SimpleIntegerProperty(3);
public static SimpleIntegerProperty myValueProperty() {
return myValue;
}
public static Integer getMyValue() {
return myValue.getValue();
}
public static void setMyValue(int value) {
myValue.set(value);
}
#FXML
private Spinner<Integer> spnMySpinner;
private ObjectProperty<Integer> spinnerValue = myValueProperty().asObject();
#Override
public void initialize(URL url, ResourceBundle rb) {
spnMySpinner.getValueFactory().valueProperty().bindBidirectional(spinnerValue);
}
}

Trying to set up an "onshowing" ActionEvent in Combobox in javafx

I'm using Scene Builder to build a javafx gui, and I want a ComboBox where something will happen "On Showing." It looks simple enough, but it crashes when I try to implement it. I created a simple version having nothing but a combobox, and it still crashes.
Here is the Main.java module:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
// BorderPane root = new BorderPane();
BorderPane root = (BorderPane) FXMLLoader.load(Main.class.getResource("Comboscreen.fxml"));
Scene scene = new Scene(root,400,400);
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);
}
}
Here is the fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<BorderPane xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
<center>
<VBox alignment="CENTER" prefHeight="400.0" prefWidth="400.0" BorderPane.alignment="CENTER">
<children>
<ComboBox fx:id="ComboTestBox" onAction="#ComboDo" onShowing="#Showaction" prefWidth="150.0" promptText="Testbox" />
</children>
</VBox>
</center>
</BorderPane>
and here is the Controller:
package application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
public class Controller {
#FXML
public ComboBox<String> ComboTestBox;
#FXML
void ComboDo(ActionEvent event) {
System.out.println(" Option Chosen");
}
ObservableList<String> options =
FXCollections.observableArrayList(
"Option 1",
"Option 2",
"Option 3"
);
#FXML
void Showaction(ActionEvent event) {
System.out.println(" TestAction");
}
public void initialize() {
ComboTestBox.setItems(options);
}
}
It looks simple enough, but it crashes every time. If I remove the "onshowing" action, it works just fine. Any advice is appreciated, as I am pretty new at this.
Assuming by "crashing" you mean it gives you a runtime exception (for future reference, please include the stack trace, which has lots of information for you to diagnose the problem, in your question):
The onShowing handler is an EventHandler<Event>, not an EventHandler<ActionEvent>, so you need:
#FXML
void Showaction(Event event) {
System.out.println(" TestAction");
}
Note that if you're not using the Event parameter, you can omit it, and the FXMLLoader will still be able to map to the correct handler method:
#FXML
void Showaction() {
System.out.println(" TestAction");
}
However, if you include the parameter, it must be of the correct type.
As an aside, you should use proper naming conventions, i.e.
#FXML
void showAction(Event event) {
System.out.println(" TestAction");
}
with the corresponding change to your FXML file.

Resources