first Java question( probably of many! ). I'm learning Java and JavaFX using Eclipse and e(fx)clispse plugin with Scene Builder 2.0. I built a small window with a couple of buttons, a TableView and an ImageView in an AnchorPane. All good so far.
My original question was going to be how how to identify the button being selected if I have only one method registered for all buttons( all two of them in my case! ). I could see the system had all the info ( by doing System.out.println for event.getSource() and event.PickResult() ). However, before posting this question, I overcame the issues but it has led to a couple of more questions;
1) For the getSource() issue, I wanted to get down to the button source information and I was expecting to be able to do it in one line. i.e. event.getSource().[ expecting Eclipse to give me methods for the Type returned by getSource() in proposals list]. However, after event.getSource()....the proposal list of methods are those which I believe are inherited from the object method. What I had to do instead was break out the statement as follows:
EventObject evo = new EventObject(event.getSource());
Object obj = evo.getSource();
Button btnMirror = (Button)obj;
System.out.println("Button id is:" + btnMirror.getId());
Why after the first event.getSource().. is getSource() not available again as a proposal?
There's clearly a gap in my understanding. After all, the list of methods I get after System.out.[method list] is different to System.in.[method list]. Could someone clarify?
2) The second question was regarding getPickResult(). When using event.getPickResult().getIntersectedNode().getId(), I was getting a null result? Can't be right I thought as printing event.getPickResult() showed it has all the info I could need. Then I tried event.getPickResult().getIntersectedNode().getParent().getId() and that worked! Aha, I thought, but alas, too early. What I discovered is that whether I got a null result, the button id, or the Anchor Pane id(!) is dependent on where exactly on the button I clicked. Bang in the middle on the button text produced a null result, slightly off centre produced the button id and the outer regions of the button( but with mouse cursor still fully inside the button ) produced the AnchorPane id. This to me makes PickResult extremely unreliable. There must be properties which are allowing this happen to. Could anyone enlighten me.
Also related to question 1, event.getPickResult().getandSoOn....always produced a list of the correct available methods after each period. Confused why this happens because the getPickResult returns a PickResult and in a similar vein, getSource return an EventType.
Thanks for any and all insights.
Attached is code for the Controller. Lots of System.out's to see what's going on. The Main is standard generated code for an FX project. Also produced the FXML code if you want to exactly replicate the window layout.
Controller code:
package myapplication;
import java.net.URL;
import java.util.EventObject;
import java.util.ResourceBundle;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventType;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.PickResult;
import javafx.scene.layout.AnchorPane;
public class IrfController implements Initializable {
@FXML private AnchorPane myAnchorPane;
@FXML private Button btnClickMe;
@FXML private Button btnAddRow;
@FXML private TableView<Person> myTV;
@FXML private TableColumn<Person, String> myCol1;
@FXML private TableColumn<Person, String> myCol2;
final ObservableList<Person> data = FXCollections.observableArrayList(
new Person("John","Smith"),
new Person("Adam", "West"));
@FXML protected void btnClick(MouseEvent event) {
/**Get source and get Pick Result both have the info**/
System.out.println( "Event GetSource: " + event.getSource());
System.out.println( "Event PickResult:" + event.getPickResult());
/** the id's of the button **/
System.out.println("Add Row buton id: " + btnAddRow.getId());
System.out.println("Click Me button id: " + btnClickMe.getId());
/**get the Node of the pick result - a direct click returns null **/
System.out.println("Pick Result Node id: " + event.getPickResult().getIntersectedNode().getId());
EventObject evo = new EventObject(event.getSource());
Object obj = evo.getSource();
Button btnMirror = (Button)obj;
System.out.println("Button id is:" + btnMirror.getId());
System.out.println( "Pick Result: " + event.getPickResult().getIntersectedNode().getParent().getId());
PickResult pkr = event.getPickResult();
Node nd = pkr.getIntersectedNode().getParent();
System.out.println("Parent Node id: " + nd.getId());
switch (btnMirror.getId()) {
case "btnClickMe": System.out.println("You selected the Click Me Button"); break;
case "btnAddRow": System.out.println("You selected the Add Row Button"); break;
default: System.out.println("No button registered"); break;
}
System.out.println("Event Type: " + event.getEventType().getName());
}
@FXML
public void onActionFired(ActionEvent event){
System.out.println("In ActionFired - Start");
System.out.println(event.getClass().toGenericString());
System.out.println(event.toString());
System.out.println(event.getEventType().toString());
System.out.println("In ActionFired - End");
}
@FXML protected void clickAnchor(MouseEvent event) {
System.out.println(event.toString());
System.out.println("Hello Click Anchor!");
System.out.println(event.getEventType().toString());
}
And the FXML file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.effect.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="myAnchorPane" onMouseClicked="#clickAnchor" prefHeight="441.0" prefWidth="578.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="myapplication.IrfController">
<children>
<Button fx:id="btnClickMe" layoutX="481.0" layoutY="135.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onMouseClicked="#btnClick" prefHeight="50.0" prefWidth="83.0" text="ClickMe" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="135.0">
<opaqueInsets>
<Insets />
</opaqueInsets>
<effect>
<Glow />
</effect></Button>
<ImageView fitHeight="100.0" fitWidth="143.0" layoutX="35.0" layoutY="22.0" pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="344.0" AnchorPane.topAnchor="22.0">
<image>
<Image url="@../../../../../Users/Ayesha/Pictures/2014-03-06/IMG_0324.JPG" />
</image>
</ImageView>
<TableView fx:id="myTV" layoutX="35.0" layoutY="135.0" prefHeight="264.0" prefWidth="396.0" AnchorPane.bottomAnchor="42.0" AnchorPane.leftAnchor="35.0" AnchorPane.rightAnchor="147.0" AnchorPane.topAnchor="135.0">
<columns>
<TableColumn fx:id="myCol1" prefWidth="75.0" text="First Name" />
<TableColumn fx:id="myCol2" prefWidth="100.0" text="Last Name" />
<TableColumn fx:id="myCol3" prefWidth="140.0" text="Something Else" />
</columns>
</TableView>
<Button fx:id="btnAddRow" layoutX="481.0" layoutY="204.0" mnemonicParsing="false" onMouseClicked="#btnClick" prefHeight="50.0" prefWidth="83.0" text="Add Row" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="204.0" />
</children>
</AnchorPane>
onAction
instead ofonMouseClicked
for a Button. – James_DEventHandler
interface, when you use different handlers) with a switch (or equivalent sequence ofif
/else
constructs). That's just generally bad practice (it will get ugly when you have 200 menu items) and in theory performance is worse (though in any real application you won't notice a difference). – James_D