简体   繁体   中英

How can I write my code more efficiently for use with different types of JavaFX GUI components?

I am making a basic JavaFX GUI, where I would like a label to change when I am hovering over different types of GUI components.

For example below, I want my label to change text from 'Bored' to 'Hovered!' when I hover over either a ComboBox, TextField, Button, Circle etc

Instead of repeating the same code over again, I am guessing I could create a method with the object as the input argument, but I can't seem to quite get it right.

Essentially, is there an elegant way I can adapt this code so that it can be reusable for all types of different JavaFX GUI components?

The following code currently does exactly what I describe, but is something that I would like to be more efficient.

Thanks.

        comboBox.setOnMouseEntered(new EventHandler<MouseEvent>() {
          @Override public void handle(MouseEvent mouseEvent) {
            label.setCursor(Cursor.HAND);
            label.setText("Hovered!");
          }
        });
        comboBox.setOnMouseExited(new EventHandler<MouseEvent>() {
          @Override public void handle(MouseEvent mouseEvent) {
            label.setCursor(Cursor.MOVE);
            label.setText("Bored");
          }
        });

        textField.setOnMouseEntered(new EventHandler<MouseEvent>() {
              @Override public void handle(MouseEvent mouseEvent) {
                label.setCursor(Cursor.HAND);
                label.setText("Hovered!");
              }
            });
        textField.setOnMouseExited(new EventHandler<MouseEvent>() {
          @Override public void handle(MouseEvent mouseEvent) {
            label.setCursor(Cursor.MOVE);
            label.setText("Bored");
          }
        });

        button.setOnMouseEntered(new EventHandler<MouseEvent>() {
              @Override public void handle(MouseEvent mouseEvent) {
                label.setCursor(Cursor.HAND);
                label.setText("Hovered!");
              }
            });
        button.setOnMouseExited(new EventHandler<MouseEvent>() {
          @Override public void handle(MouseEvent mouseEvent) {
            label.setCursor(Cursor.MOVE);
            label.setText("Bored");
          }
        });

        circle.setOnMouseEntered(new EventHandler<MouseEvent>() {
              @Override public void handle(MouseEvent mouseEvent) {
                label.setCursor(Cursor.HAND);
                label.setText("Hovered!");
              }
            });
        circle.setOnMouseExited(new EventHandler<MouseEvent>() {
          @Override public void handle(MouseEvent mouseEvent) {
            label.setCursor(Cursor.MOVE);
            label.setText("Bored");
          }
        });

You can easily use a helper method to register all those listeners. Furthermore you can reuse the listeners, since they contain the same code for all of the nodes:

private static void registerListeners(final Label label, Node... nodes) {
    final EventHandler<MouseEvent> enteredHandler = new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent mouseEvent) {
            label.setCursor(Cursor.HAND);
            label.setText("Hovered!");
        }
    };

    final EventHandler<MouseEvent> exitedHandler = new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent mouseEvent) {
            label.setCursor(Cursor.MOVE);
            label.setText("Bored");
        }
    };

    // add listeners to all nodes
    for (Node n : nodes) {
         n.setOnMouseEntered(enteredHandler);
         n.setOnMouseExited(exitedHandler);
    }
}
registerListeners(label, comboBox, textField, button);

Note that you cannot handle the MOUSE_ENTERED and the MOUSE_EXITED event on a parent node, since the event is not passed through the hierarchy. The only way to make this work for arbitrary children would be to handle the MOUSE_MOVED event on the parent. In this case you cannot be sure the intersected node is one of the nodes you want to allow. It could be a child. Therefore you need to iterate through the hierarchy yourself:

commonAncestor.setOnMouseEntered(evt -> {
    Node n = evt.getPickResult().getIntersectedNode();
    while (n != commonAncestor) {
        if (checkNode(n)) {
            label.setCursor(Cursor.HAND);
            label.setText("Hovered!");
            return;
        }
        n = n.getParent();
    }

    label.setCursor(Cursor.MOVE);
    label.setText("Bored");
});

I don't really know if this was the best answer. But you can try this:

@Override
public void initialize(URL location, ResourceBundle resources) {
combobox.setOnMouseEntered(this);
    combobox.setOnMouseExited(this);
    textfield.setOnMouseEntered(this);
    textfield.setOnMouseExited(this);
    button.setOnMouseEntered(this);
    button.setOnMouseExited(this);

}

@Override
public void handle(MouseEvent event) {
    switch (event.getEventType().getName()){
        case "MOUSE_ENTERED":
            label.setCursor(Cursor.HAND);
            label.setText("Hovered!");
            break;
        case "MOUSE_EXITED":
            label.setCursor(Cursor.MOVE);
            label.setText("Bored");
            break;
    }
}

Your controller must implement EventHandler

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM