Why can't I println "left" when left arrow is pressed? - javafx

public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
Scene scene = new Scene(root, 400, 400);
EventHandler eventHandler = new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
System.out.println("handle");
if(event.getCode().equals(KeyCode.LEFT)) {
System.out.println("left");
}
}
};
Circle circle = new Circle(200,200,100);
circle.setFill(Color.AQUAMARINE);
circle.setOnKeyPressed(eventHandler);
root.getChildren().add(circle);
stage.setTitle("JavaFX GUI");
stage.setScene(scene);
stage.show();
}
Why can't I println "left" when left arrow is pressed ? I don't understand... It is a JavaFX Application...
I want that when I type left arrow in my keyboard, this prinln "left"

You added the listener to a Node that doesn't receive the focus. Add it to the Scene instead:
scene.setOnKeyPressed(eventHandler);
or set the focusTraversable property of the Circle to true:
circle.setFocusTraversable(true);

Related

Events for two overlay shapes

My problem:
I have a two overlay shapes, for example, two rectangles: A and B.
When B overlay A rectangle.
I add setOnMouseMoved handlers for both and i see that events handles only by top figure.
Code example:
public class MainExample extends Application {
#Override
public void start(Stage stage) {
stage.setMinWidth(700);
stage.setMaxWidth(700);
stage.setMinHeight(800);
stage.setMaxHeight(800);
StackPane root = new StackPane();
var a = new Rectangle(300, 300, Color.BLUE);
var b = new Rectangle(200, 200);
root.getChildren().addAll(a, b);
b.setOnMouseMoved(mouseEvent -> {
System.out.println("Mouse moved b!");
});
a.setOnMouseMoved(mouseEvent -> System.out.println("Mouse moved a!"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
What i want:
In the area of overlapping figures mouse moved events handles both of figures: A and B.
Thanx everyone for help!
I replace both mouse events to just one in stackpane node . The event checks if mouse coords is inside in both bounds (node a and node b) . When the mouse is in an area that intersetcs both rectangles the event wil thrigger both print statments
public class MainExample extends Application {
#Override
public void start(Stage stage) {
stage.setMinWidth(700);
stage.setMaxWidth(700);
stage.setMinHeight(800);
stage.setMaxHeight(800);
StackPane root = new StackPane();
var a = new Rectangle(300, 300, Color.BLUE);
var b = new Rectangle(200, 200);
root.getChildren().addAll(a, b);
root.setOnMouseMoved(mouseEvent -> {
if(b.getBoundsInParent().contains(mouseEvent.getSceneX(),mouseEvent.getSceneY())){
System.out.println("Mouse moved b!");}
if(a.getBoundsInParent().contains(mouseEvent.getSceneX(),mouseEvent.getSceneY())){
System.out.println("Mouse moved a!");}
});
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}

JavaFX listener to a visible part of VBox

I have a JavaFX VBox inside a BorderPane (central). The content of the VBox is calculated using some business logic and it depends on the height of the visible part of the vbox.
So basically I need a listener watching changes of the visible height of the vbox = height of the central part of the border pane.
The following code demonstrates what I have tried:
public class HelloFX extends Application {
#Override
public void start(Stage primaryStage) {
VBox vbox = new VBox();
vbox.boundsInParentProperty()
.addListener((obs, oldValue, newValue) ->
System.out.println(newValue.getHeight()));
Button button = new Button("ADD LINE");
button.setPrefHeight(25);
button.setOnAction(event ->
vbox.getChildren().add(new Label("line")));
BorderPane borderPane = new BorderPane();
borderPane.setCenter(vbox);
borderPane.setTop(button);
Scene scene = new Scene(borderPane, 100, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch();
}
BorderPane with simple button on the top position and VBox on the central. The button click adds one line to vBox. Total scene height is 100, 25 is the button height and the rest (75) is the vBox.
I'm looking for some listener to report changes of the height of the central part of border pane. So in my example it should always print "75" no matter how many lines I have added to the vBox. The only event changing the value should be resizing the whole window. In reality once the vBox is filled my listener reports increasing height values. Apparently the height property includes the invisible part of the vbox.
EDIT
Finally I've found some solution - placing the vBox in the ScrollPane with disabled scrollbars. Then I can simply listen on the height property of the scrollpane and everything works as expected.
public class HelloFX extends Application {
#Override
public void start(Stage primaryStage) {
VBox vbox = new VBox();
ScrollPane scrollPane = new ScrollPane();
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scrollPane.setContent(vbox);
scrollPane.heightProperty()
.addListener((obs, oldValue, newValue) ->
System.out.println(newValue));
Button button = new Button("ADD LINE");
button.setPrefHeight(25);
button.setOnAction(event ->
vbox.getChildren().add(new Label("line")));
BorderPane borderPane = new BorderPane();
borderPane.setCenter(scrollPane);
borderPane.setTop(button);
Scene scene = new Scene(borderPane, 100, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch();
}
}

How to create own window rather then use default window

I've been working on javafx and i want to remove default windows and create a window with my style
It's quite easy to create a window in javafx. To create your own window you need to modify the style of your stage which can be done using initStyle() method.
public class Test extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(createParent(), Color.TRANSPARENT);
primaryStage.initStyle(StageStyle.TRANSPARENT);
// primaryStage.initStyle(StageStyle.UNDECORATED);
// primaryStage.initStyle(StageStyle.DECORATED);
primaryStage.setTitle("My Own Window");
primaryStage.setScene(scene);
primaryStage.show();
}
private Parent createParent() {
Pane rootPane = new Pane();
rootPane.setPrefSize(1000,400);
Button btn = new Button("RandomButton");
btn.setOnAction(e -> Platform.exit());
rootPane.getChildren().add(btn);
return rootPane;
}
}

How can I assign an EventListener to a Path in javafx?

I have this piece of code which doesn't work correctly.
I want to set a listener for when a user clicks inside the square, yet
neither the pop-up nor the message "clicked" are displayed when I click
inside the square.
What am I missing?
This method is inside the Coords class.
public static void drawMyShape(final GraphicsContext ctx) {
Path path = new Path();
MoveTo mT = new MoveTo();
LineTo lT[] = new LineTo[4];
mT.setX(200.0);
mT.setY(200.0);
lT[0] = new LineTo(400.0, 200.0);
lT[1] = new LineTo(400.0, 400.0);
lT[2] = new LineTo(200.0, 400.0);
lT[3] = new LineTo(200.0, 200.0);
path.setStroke(Color.BEIGE);
path.getElements().addAll(mT, lT[0], lT[1], lT[2], lT[3]);
path.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(Main.prim_stage);
VBox box = new VBox(20);
box.getChildren().add(new Text("Hey"));
Scene s = new Scene(box, 300, 200);
dialog.setScene(s);
dialog.show();
System.out.println("Clicked");
}
});
ctx.setLineWidth(4.0);
ctx.beginPath();
ctx.moveTo(mT.getX(), mT.getY());
for (int i = 0; i < lT.length; i++) {
ctx.lineTo(lT[i].getX(), lT[i].getY());
}
ctx.closePath();
ctx.stroke();
}
EDITED ON SUGGESTION by users.
So his is the main program:
public class Main extends Application {
public static Pane root;
private static Canvas main_canvas;
private static GraphicsContext ctx;
private static Rectangle2D bounds;
private static Scene scene;
public static Stage prim_stage;
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Switzerland Advertising");
initElements(primaryStage);
Coords.drawMyShape(ctx);
primaryStage.show();
System.out.println("Launched");
}
public static void main(String[] args) {
launch(args);
}
}
Everything is instanciated inside the following function, which works correctly and displays a full screen application with a canvas and a square drawn into it (image at the bottom).
private void initElements(final Stage primaryStage) {
prim_stage = primaryStage;
// ----------------------------------------
bounds = Screen.getPrimary().getVisualBounds();
double w = bounds.getWidth();
double h = bounds.getHeight();
// ----------------------------------------
// init elements of scene
root = new Pane();
main_canvas = new Canvas(w, h);
// ----------------------------------------
// init scene elements
scene = new Scene(root, w, h);
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setWidth(w);
primaryStage.setHeight(h);
primaryStage.setScene(scene);
// ----------------------------------------
ctx = main_canvas.getGraphicsContext2D();
// set elements in main pane
root.getChildren().add(main_canvas);
// ----------------------------------------
}
So how can I make the pop-up window appear whenever I click inside the region drawn on the canvas?
This is the program
Your path is just a local variabl within your method. It has to be attached to the scene graph in order to get events. But when you attach it to the scene graph, drawing the same path on a canvas also does not make much sense.

JavaFX Transition - Darken button on hover

I'm a beginner in JavaFX. I'm trying to create my own Button subclass that would have its on animations for mouse enter and mouse exit. The animation I'm trying to achieve is a simple "darken" or "dim" transition that would darken the color of the button background when user hovers over the button , and would animate back to normal state when the mouse exits the button.
First I thought I can achieve this with FillTransition, but for that I would need the specific darker color of the button, that depends on the button color.
So now I'm trying to basically fade in and fade out a low-opacity black rectangle on top of the button, but the rectangle doesn't seem to appear at all.
Here's the code of my button:
public class FlatButton extends Button {
private Rectangle dimRectangle;
private Duration dimDuration = Duration.millis(250);
private Color dimColor = new Color(0,0,0,0.11);
public FlatButton(String text) {
super(text);
getStyleClass().addAll("flat-button-style");
createEffect();
}
private void createEffect()
{
dimRectangle = new Rectangle(this.getWidth(), this.getHeight(), dimColor);
dimRectangle.setOpacity(1.0);
dimRectangle.setX(this.get);
FadeTransition enterTransition = new FadeTransition(dimDuration, this);
enterTransition.setInterpolator(Interpolator.EASE_OUT);
enterTransition.setFromValue(0.0);
enterTransition.setToValue(1.0);
FadeTransition exitTransition = new FadeTransition(dimDuration, this);
exitTransition.setInterpolator(Interpolator.EASE_OUT);
exitTransition.setFromValue(1.0);
exitTransition.setToValue(0.0);
this.setOnMouseEntered(new EventHandler<MouseEvent>(){
public void handle(MouseEvent mouseEvent){
enterTransition.play();
}
});
this.setOnMouseExited(new EventHandler<MouseEvent>(){
public void handle(MouseEvent mouseEvent){
exitTransition.play();
}
});
}
}
EDIT: The part in the code "new FadeTransition(dimDuration, this);" should be "new FadeTransition(dimDuration, dimRectangle);". It's just something I was testing.
EDIT2: I figured that "dimRectangle = new Rectangle(this.getWidth(), this.getHeight(), dimColor);" is not really working , but I havent found a way yet how to make the rectangle fill the button dimensions.
You could use a ColorAdjust effect and change it's brightness property using a Timeline.
public class ButtonFadeDemo extends Application {
#Override
public void start(Stage primaryStage) {
try {
Pane root = new Pane();
Button button = new Button("Click me!");
ColorAdjust colorAdjust = new ColorAdjust();
colorAdjust.setBrightness(0.0);
button.setEffect(colorAdjust);
button.setOnMouseEntered(e -> {
Timeline fadeInTimeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new KeyValue(colorAdjust.brightnessProperty(), colorAdjust.brightnessProperty().getValue(), Interpolator.LINEAR)),
new KeyFrame(Duration.seconds(1), new KeyValue(colorAdjust.brightnessProperty(), -1, Interpolator.LINEAR)
));
fadeInTimeline.setCycleCount(1);
fadeInTimeline.setAutoReverse(false);
fadeInTimeline.play();
});
button.setOnMouseExited(e -> {
Timeline fadeOutTimeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new KeyValue(colorAdjust.brightnessProperty(), colorAdjust.brightnessProperty().getValue(), Interpolator.LINEAR)),
new KeyFrame(Duration.seconds(1), new KeyValue(colorAdjust.brightnessProperty(), 0, Interpolator.LINEAR)
));
fadeOutTimeline.setCycleCount(1);
fadeOutTimeline.setAutoReverse(false);
fadeOutTimeline.play();
});
root.getChildren().addAll(button);
Scene scene = new Scene(root, 800, 400);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}

Resources