I'm trying to implemenet GUI on some kind of Doubly Linked list - javafx

I've so far done this, it's adding labels on the stage but removing thing is working but not as intended...
How can I store data of labels in an array or something so I can compare the remove.getText(); with that and delete that typed value if previous added as a label on stage.
public class Main extends Application {
Group root;
Label label1,label;
int count=1,count1=1;
public static void main(String[] args) {launch(args);}
public void start(Stage stage) throws Exception {
stage.setTitle("LinkedList GUI");
stage.setResizable(false);
root = new Group();
LinkedList<Integer> Linked =new LinkedList<Integer>();
Button Addfirst = new Button("AddFirst");
Addfirst.setTranslateX(40);
Addfirst.setTranslateY(350);
TextField first=new TextField();
first.setPrefWidth(60);
first.setTranslateX(120);
first.setTranslateY(350);
Addfirst.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
int a = Integer.parseInt(first.getText());
Linked.addFirst(a);
label1=new Label(" "+first.getText());
label1.setFont(Font.font("Buxton Sketch",FontWeight.BOLD,FontPosture.ITALIC,12));
label1.setPrefWidth(25);
label1.setPrefHeight(25);
label1.setTranslateY(60);
label1.setTextFill(Color.GREEN );
label1.setStyle("-fx-border-color: Blue;");
root.getChildren().addAll(label1);
label1.setTranslateX(250-(20*count++));
count++;
}
});
Button Addlast = new Button("AddLast");
Addlast.setTranslateX(200);
Addlast.setTranslateY(350);
TextField last=new TextField();
last.setPrefWidth(60);
last.setTranslateX(270);
last.setTranslateY(350);
Addlast.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
int b= Integer.parseInt(last.getText());
Linked.addLast(b);
label=new Label(" "+last.getText());
label.setFont(Font.font("Buxton Sketch",FontWeight.BOLD,FontPosture.ITALIC,12));
label.setPrefWidth(25);
label.setPrefHeight(25);
label.setTranslateY(60);
label.setTextFill(Color.GREEN );
label.setStyle("-fx-border-color: Blue;");
root.getChildren().add(label);
label.setTranslateX(250+(20*count1++));
count1++;
}
});
Button delete = new Button("Delete");
delete.setTranslateX(350);
delete.setTranslateY(350);
TextField remove=new TextField();
remove.setPrefWidth(60);
remove.setTranslateX(420);
remove.setTranslateY(350);
delete.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
if(remove.getText().equals(first.getText())) {
Linked.remove(first.getText());
root.getChildren().remove(label1);
}
else if(remove.getText().equals(last.getText())) {
Linked.remove(last.getText());
root.getChildren().remove(label);
}
else {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setContentText("Not in List");
alert.showAndWait();
}
}
});
Text text =new Text("Doubly LinkedList GUI");
text.setStyle("-fx-border-color: Blak;");
text.setFont(Font.font("Buxton Sketch",FontWeight.BOLD,FontPosture.ITALIC,16));
text.setTranslateX(150);
text.setTranslateY(30);
root.getChildren().addAll(text,Addfirst,first,Addlast,last,delete,remove);
Scene scene = new Scene(root,500,400);
stage.setScene(scene);
stage.show();
}
}

I recommend using a layout that positions the children for you instead of positioning them yourself. E.g. using a HBox as parent for the labels allows you to simply add/remove the child at the same index as the one added/removed in the list:
#Override
public void start(Stage stage) throws Exception {
HBox container = new HBox(20);
container.setPrefHeight(40);
Button addFirst = new Button("add head");
Button addLast = new Button("add tail");
Button remove = new Button("remove");
TextField textField = new TextField();
HBox buttonContainer = new HBox(10, textField, addFirst, addLast, remove);
final LinkedList<Integer> list = new LinkedList<>();
addFirst.setOnAction(evt -> {
String text = textField.getText();
Integer value = Integer.parseInt(text);
list.addFirst(value);
container.getChildren().add(0, new Label(text));
});
addLast.setOnAction(evt -> {
String text = textField.getText();
Integer value = Integer.parseInt(text);
list.addLast(value);
container.getChildren().add(new Label(text));
});
remove.setOnAction(evt -> {
String text = textField.getText();
int value = Integer.parseInt(text);
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()) {
Integer element = iterator.next();
if (element == value) {
container.getChildren().remove(iterator.nextIndex() - 1);
iterator.remove();
break;
}
}
});
VBox root = new VBox(container, buttonContainer);
Scene scene = new Scene(root, 500, 400);
stage.setScene(scene);
stage.show();
}

Related

How to corectly obtain the outer bounds of a node in JavaFX

I am trying to manually align nodes on a JavaFX Pane, but can't seem to be able to get the actual outer bounds of the nodes.
I don't know how better to explain the problem than by showing the following example I created to demonstrate it:
This window is generated by the following code:
public class JavaFXMWE extends Application {
private Pane root;
#Override
public void start(Stage primaryStage) {
root = new Pane();
normal();
bold();
inStackPane();
inStackPaneWithInsets();
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("MWE");
primaryStage.setScene(scene);
primaryStage.show();
}
private void normal() {
Text text1 = new Text("Some Text");
Text text2 = new Text("Some other Text");
text1.relocate(20, 20);
text2.relocate(text1.getBoundsInParent().getMaxX(), 20);
root.getChildren().addAll(text1, text2);
}
private void bold() {
Text text1 = new Text("Some Text");
Text text2 = new Text("Some other Text");
text1.setStyle("-fx-font-weight: bold");
text2.setStyle("-fx-font-weight: bold");
text1.relocate(20, 40);
text2.relocate(text1.getBoundsInParent().getMaxX(), 40);
root.getChildren().addAll(text1, text2);
}
private void inStackPane() {
Text text1 = new Text("Some Text");
Text text2 = new Text("Some other Text");
StackPane pane1 = new StackPane(text1);
StackPane pane2 = new StackPane(text2);
setBorder(pane1);
setBorder(pane2);
pane1.relocate(20, 60);
pane2.relocate(pane1.getBoundsInParent().getMaxX(), 60);
root.getChildren().addAll(pane1, pane2);
}
private void inStackPaneWithInsets() {
Text text1 = new Text("Some Text");
Text text2 = new Text("Some other Text");
StackPane pane1 = new StackPane(text1);
StackPane pane2 = new StackPane(text2);
setBorderAndInsets(pane1);
setBorderAndInsets(pane2);
pane1.relocate(20, 85);
pane2.relocate(pane1.getBoundsInParent().getMaxX(), 85);
root.getChildren().addAll(pane1, pane2);
}
private static void setBorder(Region node) {
node.setBorder(new Border(new BorderStroke(Color.BLACK,
BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
}
private static void setBorderAndInsets(Region node) {
setBorder(node);
node.setPadding(new Insets(5));
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
How do I obtain the actual outer bounds of the nodes?
The CSS style is applied just before the first layout pass. The style property has no effect on the node until this happens. For this reason positioning children yourself is best done by overriding the layoutChildren method; this method is invoked during the layout pass. Alternatively you could add a listener to the boundsInParent property.
#Override
public void start(Stage primaryStage) throws Exception {
Text text1 = new Text("Some Text");
Text text2 = new Text("Some other Text");
text1.setStyle("-fx-font-weight: bold");
text2.setStyle("-fx-font-weight: bold");
Pane root = new Pane(text1, text2) {
#Override
protected void layoutChildren() {
text1.relocate(20, 40);
text2.relocate(text1.getLayoutX() + text1.prefWidth(-1), 40); // using text1.boundsInParent would work too, usually the size constraints returned by the minWidth, prefWidth and maxWidth methods should be used
}
};
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
}

How to get data from Tab in Tabpane JavaFX

I want get data from Tab in Tabpane JavaFX
I have 2 Tab in Tabpane, And each Tab I have a TextArea, I want click Button will get data from 2 tab
Here's my code:
btnThem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
try {
i++;
FXMLLoader fxmlLoader = new FXMLLoader(
getClass().getResource("/fxml/tab.fxml"));
Parent parent = (Parent) fxmlLoader.load();
Tab tab = new Tab("Điểm " + i);
tab.setContent(parent);
tab.setClosable(true);
tabPane.getTabs().add(tab);
controllerTab = (ControllerTab) fxmlLoader.getController();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
});
Your question is ambiguous but it seems you want to get data from each textArea in tab.To do this you should get nodes (children) from each tab and by using lookup() we confirm and we parse node to textArea.I tried to figure your scene and made this example to help you :
public class example extends Application {
TextArea textArea = new TextArea();
TextArea textArea1 = new TextArea();
Button button = new Button("button");
#Override
public void start(Stage primaryStage) {
Tab tab1 = new Tab("tab1");
Tab tab2 = new Tab("tab2");
tab1.setContent(textArea);
tab2.setContent(textArea1);
TabPane pane = new TabPane();
pane.getTabs().addAll(tab1, tab2);
Node node1 = tab1.getContent();
Node node2 = tab2.getContent();
button.setOnAction((ActionEvent event) -> {
if (node1.lookup("TextArea") != null && node2.lookup("TextArea") != null) {
TextArea area1 = (TextArea) node1.lookup("TextArea");
TextArea area2 = (TextArea) node2.lookup("TextArea");
System.out.println(area1.getText() + " " + area2.getText());
}
});
VBox root = new VBox();
root.setAlignment(Pos.TOP_RIGHT);
root.getChildren().add(pane);
root.getChildren().add(button);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
And you can see the result :
Hello ,tab1 Hello ,tab2
Deleting directory C:\Users\Electron\Documents\NetBeansProjects\Buttono\dist\run341573612
jfxsa-run:
BUILD SUCCESSFUL (total time: 22 seconds)

JavaFX cannot close scene by Esc using getAccelerators() [duplicate]

Im calling a new stage in my program which I like to close on pressing escape. I did this which gives me a NullPointerException:
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
KeyCode key = t.getCode();
if (key == KeyCode.ESCAPE){
stage.close();
}
}
});
try this..
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>
() {
#Override
public void handle(KeyEvent t) {
if(t.getCode()==KeyCode.ESCAPE)
{
System.out.println("click on escape");
Stage sb = (Stage)label.getScene().getWindow();//use any one object
sb.close();
}
}
});
Add the event handler to the stage/window you want to close on ESC.
JavaFX 8 style:
stage.addEventHandler(KeyEvent.KEY_RELEASED, (KeyEvent event) -> {
if (KeyCode.ESCAPE == event.getCode()) {
stage.close();
}
});
why you dont show us more of your code? However, try this:
public class Login extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage primaryStage) {
primaryStage.setTitle("JavaFX Welcome");
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Text scenetitle = new Text("Welcome");
scenetitle.setId("welcome-text");
grid.add(scenetitle, 0, 0, 2, 1);
Label userName = new Label("User Name:");
grid.add(userName, 0, 1);
TextField userTextField = new TextField();
grid.add(userTextField, 1, 1);
Label pw = new Label("Password:");
grid.add(pw, 0, 2);
PasswordField pwBox = new PasswordField();
grid.add(pwBox, 1, 2);
Button btn = new Button("Sign in");
HBox hbBtn = new HBox(10);
hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
hbBtn.getChildren().add(btn);
grid.add(hbBtn, 1, 4);
Scene scene = new Scene(grid, 660, 300);
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(KeyEvent ke) {
if (ke.getCode() == KeyCode.ESCAPE) {
System.out.println("Key Pressed: " + ke.getCode());
primaryStage.close();
}
}
});
//primaryStage.setFullScreen(true);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Done.
Hope the imported Eventhandler package is not of JavaFX.
Try using,
import javafx.event.EventHandler;
Note:As the naming convention are same but only the package name differs between swing and JavaFX, Your NetBeans/Eclipse may auto import different packages, so make sure of it.

JavaFX WhatApp-Like ConversationView

I'm trying to make a WhatsApp-Like Conversation-View in JavaFX.
In order to make the sent messages appear on the right and the received messages appear on the left then I cannot use TextArea. How can I do it? I tried GridPane without TextArea but it didn't make things easier.
Moreover, is it a good practice to make controls static?
Extra: if you can also help me do the chat bubble behind the text, it would be great.
Here is my code:
public class ConversationView implements WhatAppView {
private static Label nameLabel, statusLabel;
private static TextField messageTextField;
static TextArea messagesTextArea;
private static GridPane conversationSection;
private static Label changeViewLink;
private static Button sendMsgButton;
// private static int rowIndex = 1;
public void showView() {
AppMain.stage.setResizable(false);
AppMain.stage.setWidth(350);
AppMain.stage.setHeight(550);
BorderPane rootPane = new BorderPane();
rootPane.setPadding(new Insets(5, 5, 5, 5));
final int sectionHeight = 55;
StackPane contactSection = new StackPane();
nameLabel = new Label("RW");
statusLabel = new Label("Online");
changeViewLink = new Label("Go Back");
changeViewLink.setStyle("-fx-text-fill: blue;");
changeViewLink.styleProperty().bind(
Bindings.when(changeViewLink.hoverProperty())
.then(new SimpleStringProperty("-fx-underline: true; -fx-text-fill: blue;"))
.otherwise(new SimpleStringProperty("-fx-underline: false; -fx-text-fill: blue;")));
changeViewLink.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
AppMain.changeView(new ChatsView());
}
});
contactSection.getChildren().addAll(nameLabel, statusLabel, changeViewLink);
StackPane.setAlignment(changeViewLink, Pos.TOP_RIGHT);
StackPane.setAlignment(statusLabel, Pos.BOTTOM_CENTER);
contactSection.setPrefHeight(sectionHeight);
conversationSection = new GridPane();
conversationSection.setStyle("-fx-background-image: url('whatsapp-wallpaper.jpg')");
messagesTextArea = new TextArea();
messagesTextArea.setEditable(false);
// conversationSection.getColumnConstraints().addAll(new
// ColumnConstraints(AppMain.stage.getWidth()/2 - 10), new
// ColumnConstraints(AppMain.stage.getWidth()/2 - 10));
conversationSection.add(messagesTextArea, 0, 0);
conversationSection.setPrefSize(AppMain.stage.getWidth(), AppMain.stage.getHeight());
// conversationSection.getStylesheets().add("conversation.css");
ScrollPane scroll = new ScrollPane();
scroll.setPrefSize(conversationSection.getWidth(), conversationSection.getHeight());
scroll.setContent(conversationSection);
FlowPane messageSection = new FlowPane();
sendMsgButton = new Button("_Send");
sendMsgButton.setDisable(true);
sendMsgButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
sendMsg();
}
});
sendMsgButton.setPrefHeight(sectionHeight);
Tooltip sendMsgToolTip = new Tooltip("Send Message");
Tooltip.install(sendMsgButton, sendMsgToolTip);
FlowPane.setMargin(sendMsgButton, new Insets(0, 0, 0, 5));
messageTextField = new TextField();
messageTextField.setPromptText("Type your message here...");
Platform.runLater(new Runnable() { // 100% focus
public void run() {
messageTextField.requestFocus();
}
});
messageTextField.setPrefWidth(AppMain.stage.getWidth() - AppMain.stage.getWidth() / 5);
messageTextField.setPrefHeight(sectionHeight);
messageTextField.setAlignment(Pos.TOP_LEFT);
messageTextField.setOnKeyTyped(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (messageTextField.getText() != null && !messageTextField.getText().isEmpty()) {
sendMsgButton.setDisable(false);
} else {
sendMsgButton.setDisable(true);
}
}
});
messageTextField.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode().equals(KeyCode.ENTER) && messageTextField.getText() != null
&& !messageTextField.getText().isEmpty()) {
sendMsg();
}
}
});
messageSection.getChildren().add(messageTextField);
messageSection.getChildren().add(sendMsgButton);
messageSection.setPrefHeight(sectionHeight);
rootPane.setTop(contactSection);
rootPane.setCenter(conversationSection);
rootPane.setBottom(messageSection);
Scene scene = new Scene(rootPane);
AppMain.stage.setScene(scene);
AppMain.stage.setTitle("WhatsApp");
}
}
public class AppMain extends Application {
static Stage stage;
#Override
public void start(Stage primaryStage) throws Exception {
stage = primaryStage;
AppMain.stage.show();
changeView(new ConversationView());
}
public static void changeView(WhatAppView view) {
view.showView();
}
}
public interface WhatAppView {
public void showView();
}
You can create a custom control to determine message alignment and aesthetics such as the bubble like appearance. As a fan of HBox and VBox, I would recommend their usage in combination with an SVGPath to decorate the message.
SVGPath's let you draw custom shapes by providing information on the lines, arcs etc. These aren't unique to java so there are a few resources available to see some basic/advanced examples. My recommendation would be to read here: SVGPath and use the TryitEditor to experiment
Here are two quick examples:
When it comes to laying out the messages a VBox would suffice. You can bind the viewable children to an ObservableList of messages you would be able to iterate later. The added benefit of this is that adding to the list will update the UI automatically, and you'll also be able to iterate these later in the event you implement additional features such as delete, forward etc
I'd recommend reading up on the Bindings api, particularly bindContentBidirectional for more information on this
Using my above recommendations i've written a small example below you can reference. It's not visually impressive, but hopefully you can get some ideas from it, particularly this:
Extra: if you can also help me do the chat bubble behind the text, it
would be great.
The messages/speech bubbles:
enum SpeechDirection{
LEFT, RIGHT
}
public class SpeechBox extends HBox{
private Color DEFAULT_SENDER_COLOR = Color.GOLD;
private Color DEFAULT_RECEIVER_COLOR = Color.LIMEGREEN;
private Background DEFAULT_SENDER_BACKGROUND, DEFAULT_RECEIVER_BACKGROUND;
private String message;
private SpeechDirection direction;
private Label displayedText;
private SVGPath directionIndicator;
public SpeechBox(String message, SpeechDirection direction){
this.message = message;
this.direction = direction;
initialiseDefaults();
setupElements();
}
private void initialiseDefaults(){
DEFAULT_SENDER_BACKGROUND = new Background(
new BackgroundFill(DEFAULT_SENDER_COLOR, new CornerRadii(5,0,5,5,false), Insets.EMPTY));
DEFAULT_RECEIVER_BACKGROUND = new Background(
new BackgroundFill(DEFAULT_RECEIVER_COLOR, new CornerRadii(0,5,5,5,false), Insets.EMPTY));
}
private void setupElements(){
displayedText = new Label(message);
displayedText.setPadding(new Insets(5));
displayedText.setWrapText(true);
directionIndicator = new SVGPath();
if(direction == SpeechDirection.LEFT){
configureForReceiver();
}
else{
configureForSender();
}
}
private void configureForSender(){
displayedText.setBackground(DEFAULT_SENDER_BACKGROUND);
displayedText.setAlignment(Pos.CENTER_RIGHT);
directionIndicator.setContent("M10 0 L0 10 L0 0 Z");
directionIndicator.setFill(DEFAULT_SENDER_COLOR);
HBox container = new HBox(displayedText, directionIndicator);
//Use at most 75% of the width provided to the SpeechBox for displaying the message
container.maxWidthProperty().bind(widthProperty().multiply(0.75));
getChildren().setAll(container);
setAlignment(Pos.CENTER_RIGHT);
}
private void configureForReceiver(){
displayedText.setBackground(DEFAULT_RECEIVER_BACKGROUND);
displayedText.setAlignment(Pos.CENTER_LEFT);
directionIndicator.setContent("M0 0 L10 0 L10 10 Z");
directionIndicator.setFill(DEFAULT_RECEIVER_COLOR);
HBox container = new HBox(directionIndicator, displayedText);
//Use at most 75% of the width provided to the SpeechBox for displaying the message
container.maxWidthProperty().bind(widthProperty().multiply(0.75));
getChildren().setAll(container);
setAlignment(Pos.CENTER_LEFT);
}
}
Conversation window:
public class ConversationView extends VBox{
private String conversationPartner;
private ObservableList<Node> speechBubbles = FXCollections.observableArrayList();
private Label contactHeader;
private ScrollPane messageScroller;
private VBox messageContainer;
private HBox inputContainer;
public ConversationView(String conversationPartner){
super(5);
this.conversationPartner = conversationPartner;
setupElements();
}
private void setupElements(){
setupContactHeader();
setupMessageDisplay();
setupInputDisplay();
getChildren().setAll(contactHeader, messageScroller, inputContainer);
setPadding(new Insets(5));
}
private void setupContactHeader(){
contactHeader = new Label(conversationPartner);
contactHeader.setAlignment(Pos.CENTER);
contactHeader.setFont(Font.font("Comic Sans MS", 14));
}
private void setupMessageDisplay(){
messageContainer = new VBox(5);
Bindings.bindContentBidirectional(speechBubbles, messageContainer.getChildren());
messageScroller = new ScrollPane(messageContainer);
messageScroller.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
messageScroller.setHbarPolicy(ScrollBarPolicy.NEVER);
messageScroller.setPrefHeight(300);
messageScroller.prefWidthProperty().bind(messageContainer.prefWidthProperty().subtract(5));
messageScroller.setFitToWidth(true);
//Make the scroller scroll to the bottom when a new message is added
speechBubbles.addListener((ListChangeListener<Node>) change -> {
while (change.next()) {
if(change.wasAdded()){
messageScroller.setVvalue(messageScroller.getVmax());
}
}
});
}
private void setupInputDisplay(){
inputContainer = new HBox(5);
TextField userInput = new TextField();
userInput.setPromptText("Enter message");
Button sendMessageButton = new Button("Send");
sendMessageButton.disableProperty().bind(userInput.lengthProperty().isEqualTo(0));
sendMessageButton.setOnAction(event-> {
sendMessage(userInput.getText());
userInput.setText("");
});
//For testing purposes
Button receiveMessageButton = new Button("Receive");
receiveMessageButton.disableProperty().bind(userInput.lengthProperty().isEqualTo(0));
receiveMessageButton.setOnAction(event-> {
receiveMessage(userInput.getText());
userInput.setText("");
});
inputContainer.getChildren().setAll(userInput, sendMessageButton, receiveMessageButton);
}
public void sendMessage(String message){
speechBubbles.add(new SpeechBox(message, SpeechDirection.RIGHT));
}
public void receiveMessage(String message){
speechBubbles.add(new SpeechBox(message, SpeechDirection.LEFT));
}
}
Output:

Swing component in JavaFx swing node WRONG mouse events

I have a small test a JButton in a SwingNode in a Stage, using Java 8.
Problem: right click is not triggered, the middle click is interpreted as right click ...
Here is the code:
Platform.runLater(new Runnable() {
#Override
public void run() {
HBox hb = new HBox();
SwingNode n = new SwingNode();
JButton b = new JButton("CLICK ME!!!");
b.addMouseListener(new MouseAdapter() {
public final void mousePressed(MouseEvent e) {
boolean isLeftClick = SwingUtilities.isLeftMouseButton(e);
boolean isRightClick = SwingUtilities.isRightMouseButton(e);
if (isLeftClick)
System.out.println("Left");
if (isRightClick)
System.out.println("Right");
}
});
n.setContent(b);
hb.getChildren().add(n);
Stage stage = new Stage();
Scene appScene = new Scene(hb,100, 100);
stage.setScene(appScene);
stage.show();
}
});

Resources