I'm trying to create a MenuButton with multiple items. Then, when one of the items is clicked, grab it's value. But can't figure out how to do this?
Here is a snippet from my FXML:
<MenuButton fx:id="changeStatusButton" layoutX="420.0" layoutY="16.0" mnemonicParsing="false" onAction="#changeStatusFired" prefHeight="26.0" prefWidth="180.0" text="Change My Status" AnchorPane.rightAnchor="17.0">
<items>
<MenuItem mnemonicParsing="false" text="Set Available" />
<MenuItem mnemonicParsing="false" text="Set Unavailable" />
</items>
</MenuButton>
How would I go about grabbing the text from the selected item? So if the first item is selected, I would like to get the text "Set Available" to perform an action based on that. But can't figure out how to do that? For a textfield this is easy, but have no idea how these MenuButtons work. All the information I've found only tells you how to populate them, but I've already pre-populated them...
Menus and MenuButtons don't maintain a "selectedItem" state. The MenuItems fire ActionEvents when the user clicks on them (or invokes their action via a keyboard shortcut). So you need to register action listeners for them:
<MenuButton fx:id="changeStatusButton" layoutX="420.0" layoutY="16.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="180.0" text="Change My Status" AnchorPane.rightAnchor="17.0">
<items>
<MenuItem mnemonicParsing="false" onAction="#setAvailable" text="Set Available" />
<MenuItem mnemonicParsing="false" onAction="#setUnavailable" text="Set Unavailable" />
</items>
</MenuButton>
and then in your controller:
private boolean available ;
// ...
#FXML
private void setAvailable(ActionEvent event) {
available = true ;
}
#FXML
private void setUnavailable(ActionEvent event) {
available = false ;
}
If you want true selection functionality, you should consider using a ComboBox. Obviously in this example a CheckBox would be the best option, but I assume your real example has more choices.
Related
I have this zk code:
<zk>
<window apply="org.zkoss.bind.BindComposer" viewModel="#id('vm')#init('IndexViewModel')" validationMessages="#id('vmsgs')">
<menubar>
<menu>
<menuitem label="${each}" forEach="#load(vm.menupoints)" />
</menu>
</menubar>
</window>
</zk>
in my view model:
private List<String> menupoints = Arrays.asList("Home", "ShipTracking");
//getter-setter
But i get a index.zul: org.zkoss.zk.ui.UiException: Unsupported child for menu: exception...what can be a problem? My goal is to create a menu with different content...may be can anybody help with it also?
Thanks!
Menuitem is not a supported child of menu.
If you look at the documentation you see that it only supports menupopup
<menu>
<menupopup>
<menuitem label="${each}" forEach="#load(vm.menupoints)" />
</menupopup>
</menu>
I'm trying to write a simple Java app for modifying and visualizing logic circuits by dragging gates and connections about. I'm using SceneBuilder to put the interface together. Right now, I'm stuck at getting the available basic logic gates to display in their proper bar and respond to being interacted with. More accurately, I'm trying to get one gate to just display some console output, to confirm that the GUI-logic connection is working.
The biggest problem I'm having is that the ImageViews of the gates, possibly along with some other FXML elements, refuse to display in the actual compiled app for some reason, even though they work and react correctly in SceneBuilder and in its "Preview" feature.
I had to do some experimenting with wrapping them in various other FXML elements which I didn't really understand because apparently ImageWiew doesn't have a onDragDetected() method, even though the text input field for it is available in SceneBuilder. The intended work-in-progress app layout can be seen plainly enough directly from SceneBuilder on the first picture. Compare with the second one, which is of the actual running application.
Possibly relevant code:
Main.java
package main;
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{
Parent root = FXMLLoader.load(getClass().getResource("RootLayout.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 640, 450));
primaryStage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
TheCircuitController.java
package Gates;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
/**
* The class for holding all the information about gates, connections, and in and out pins in the current circuit
*/
public class TheCircuitController implements Initializable{
#FXML
private AnchorPane anchorPaneNAND;
//TODO temporarily public, make private later
public ArrayList<CircuitElement> allCircuitElements= new ArrayList<CircuitElement>();
public ArrayList<Pin> theCircuitInputPins = new ArrayList<Pin>();
public ArrayList<Pin> theCircuitOutputPins = new ArrayList<Pin>();
ArrayList<Connection> allCircuitConnections = new ArrayList<Connection>();
public ArrayList<Pin> allCircuitGateInputPins = new ArrayList<Pin>();
public ArrayList<Pin> allCircuitGateOutputPins = new ArrayList<Pin>();
public ArrayList<Gate> allCircuitGates = new ArrayList<Gate>();
private InbuiltGateType currentDragGateType;
#Override
public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
// initialize your logic here: all #FXML variables will have been injected
anchorPaneNAND.setOnDragDetected(this::handleDragDetectedNAND);
}
#FXML
private void handleDragDetectedNAND(MouseEvent mouseEvent) {
System.out.println("drag detected nand!");
}
//other stuff of the class, unrelated to FXML
}
RootLayout.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="450.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Gates.TheCircuitController">
<children>
<MenuBar prefHeight="27.0" prefWidth="562.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<SplitPane dividerPositions="0.2413793103448276" prefHeight="402.0" prefWidth="640.0">
<items>
<ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="400.0" prefWidth="122.0">
<content>
<VBox prefHeight="400.0" prefWidth="208.0" spacing="10.0">
<children>
<AnchorPane fx:id="anchorPaneNAND" onDragDetected="#handleDragDetectedNAND">
<children>
<ImageView>
<image>
<Image url="#../../resources/100px-NAND_ANSI.svg.png" />
</image>
</ImageView>
</children>
</AnchorPane>
<ImageView>
<image>
<Image url="#../../resources/100px-NOT_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-AND_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/OR_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-NOR_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-XOR_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-XNOR_ANSI.svg.png" />
</image>
</ImageView>
</children>
<padding>
<Insets left="20.0" right="20.0" />
</padding></VBox>
</content></ScrollPane>
<ScrollPane prefHeight="400.0" prefWidth="406.0" />
</items>
</SplitPane>
</children>
</VBox>
I thus need to know:
Why are those gates(or at least one) not displaying as intended? And what's with the ScrollPane, why is it not displaying its sliders as it is in SceneBuilder? What things do I need to set up differently or wiggle with to get those gates to show up and interact correctly?
After a bit of random crapshooting, I found a solution.
First, I looked into View->Show Sample Controller Skeleton. There, I noticed that the handleDragDetectedNAND() method does not have any modifier, whereas mine had private, copied early from some tutorial or the other. I removed the modifier and the application now works. If anyone who passes by cared to explain why this is the case(I have no idea and no time to research, deadline's fast approaching), the value of this answer would rise significantly.
Be sure all images inside of src folder. (tested)
The image which outsite of src folder dont appear.
+ MyProject
+ not_working_dir
+ src
+ com.stackoverflow
+ working_dir
I am building a UI using Java FX scene builder and I want a button in a toolbar to float towards the right side of the toolbar. I have tried changing the node orientation of the parent(toolbar) and also the button but both seem to be ignored.
Add a pane with no content which always grows to fit available space between the left aligned tools in the bar and right aligned ones.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<ToolBar prefHeight="40.0" prefWidth="318.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<Button text="Apples" />
<Button text="Oranges" />
<Pane HBox.hgrow="ALWAYS" />
<Button text="Help" />
</ToolBar>
(Verified in Scene Builder 11.0.0)
One option: Use two ToolBar containers wrapped with an HBox container. Put the Help button in the right ToolBar. Put the left-aligned buttons in the left toolbar. For the left ToolBar, set the HGrow to ALWAYS. For the Right ToolBar, set HGrow to NEVER. For each ToolBar, set all Sizes to USE_COMPUTED_SIZE.
Here is the relevant fxml:
<HBox VBox.vgrow="NEVER">
<children>
<ToolBar HBox.hgrow="ALWAYS">
<items>
<Button text="Apples" />
<Button text="Oranges" />
</items>
</ToolBar>
<ToolBar HBox.hgrow="NEVER">
<items>
<Button text="Help" />
</items>
</ToolBar>
</children>
</HBox>
This is the hierarchy as displayed in Scene Builder:
This is the display within Scene Builder:
If you could place ur button inside a stack pane then u could make use of Stackpane's alignment property that takes javafx.geometry.Pos - The alignment of the child within the stackpane.For example in ur case:
<StackPane >
<Button translateY="-15" translateX="15" StackPane.alignment="TOP_RIGHT"/>
</StackPane>
BorderPane mainBorderPane = new BorderPane();
BorderPane ToolBorderPane = new BorderPane();
ToolBar tBarLeft=new ToolBar();
ToolBar tBarRight=new ToolBar();
ToolBorderPane.setLeft(tBarLeft);
ToolBorderPane.setRight(tBarRight);
mainBorderPane.setTop(ToolBorderPane);
...
...
for your left aligment items add tBarLeft and
your right aligment items add tBarRight
It can be done with some hack: apply 180 degree rotation around Y-axis for the toolbar and all its buttons.
<ToolBar rotate="-180.0" HBox.hgrow="ALWAYS">
<items>
<Button mnemonicParsing="false" rotate="180.0" text="Button">
<rotationAxis>
<Point3D y="1.0" />
</rotationAxis>
</Button>
</items>
<rotationAxis>
<Point3D y="1.0" />
</rotationAxis>
</ToolBar>
I am building a UI using Java FX scene builder and I want a button in a toolbar to float towards the right side of the toolbar. I have tried changing the node orientation of the parent(toolbar) and also the button but both seem to be ignored.
Add a pane with no content which always grows to fit available space between the left aligned tools in the bar and right aligned ones.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<ToolBar prefHeight="40.0" prefWidth="318.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<Button text="Apples" />
<Button text="Oranges" />
<Pane HBox.hgrow="ALWAYS" />
<Button text="Help" />
</ToolBar>
(Verified in Scene Builder 11.0.0)
One option: Use two ToolBar containers wrapped with an HBox container. Put the Help button in the right ToolBar. Put the left-aligned buttons in the left toolbar. For the left ToolBar, set the HGrow to ALWAYS. For the Right ToolBar, set HGrow to NEVER. For each ToolBar, set all Sizes to USE_COMPUTED_SIZE.
Here is the relevant fxml:
<HBox VBox.vgrow="NEVER">
<children>
<ToolBar HBox.hgrow="ALWAYS">
<items>
<Button text="Apples" />
<Button text="Oranges" />
</items>
</ToolBar>
<ToolBar HBox.hgrow="NEVER">
<items>
<Button text="Help" />
</items>
</ToolBar>
</children>
</HBox>
This is the hierarchy as displayed in Scene Builder:
This is the display within Scene Builder:
If you could place ur button inside a stack pane then u could make use of Stackpane's alignment property that takes javafx.geometry.Pos - The alignment of the child within the stackpane.For example in ur case:
<StackPane >
<Button translateY="-15" translateX="15" StackPane.alignment="TOP_RIGHT"/>
</StackPane>
BorderPane mainBorderPane = new BorderPane();
BorderPane ToolBorderPane = new BorderPane();
ToolBar tBarLeft=new ToolBar();
ToolBar tBarRight=new ToolBar();
ToolBorderPane.setLeft(tBarLeft);
ToolBorderPane.setRight(tBarRight);
mainBorderPane.setTop(ToolBorderPane);
...
...
for your left aligment items add tBarLeft and
your right aligment items add tBarRight
It can be done with some hack: apply 180 degree rotation around Y-axis for the toolbar and all its buttons.
<ToolBar rotate="-180.0" HBox.hgrow="ALWAYS">
<items>
<Button mnemonicParsing="false" rotate="180.0" text="Button">
<rotationAxis>
<Point3D y="1.0" />
</rotationAxis>
</Button>
</items>
<rotationAxis>
<Point3D y="1.0" />
</rotationAxis>
</ToolBar>
Take for example the menu items from the edit menu in JavaFX Scene Builder
See how they display the shortcuts on the right? Is there any easy way to achieve the same effect using JavaFX? Thanks.
You can add an accelerator key in scene builder or add it directly in the fxml file like so
<?import javafx.scene.input.*?>
...
<MenuItem mnemonicParsing="true" onAction="#mnuSaveAction" text="%menu.title.save" fx:id="mnuSave">
<accelerator>
<KeyCodeCombination alt="UP" code="S" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
</accelerator>
</MenuItem>
KeyCodeCombination has two constructors, second example:
<MenuItem text="Renommer..." onAction="#rename" mnemonicParsing="true">
<accelerator>
<KeyCodeCombination code="F2"><modifiers></modifiers></KeyCodeCombination>
</accelerator>
</MenuItem>
If by "in javafx" you mean without using fxml you can use mnuSave.setAccelerator(KeyCombination);
If your are not using fxml file then you can add key combination like below.
MenuItem gotoLine = new MenuItem("Goto");
KeyCombination gotoKeyCombination = new KeyCodeCombination(KeyCode.G, KeyCombination.CONTROL_DOWN);
gotoLine.setAccelerator(gotoKeyCombination);
gotoLine.setOnAction(event -> {
System.out.println("CTRL+G event triggered");
System.out.println(event.toString());
});