Reputation: 587
I want to click on one of three button on title of my internal window to change its color to black. but it some times works and sometimes does`nt work. please look at my code an tell me whats wrong with it!?
I used javac 1.8u20 to compile and jre 1.9 to run... if we use to or three layer of Pane inside of each other how the events handle? is there problem?
package core.windowManager;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Screen;
import static javafx.scene.paint.Color.rgb;
/**
* Created by yn on 22/08/17.
* just declare a win not more ...
*/
public class win {
/**
* where we add the win to it in scene
*/
private final AnchorPane root;
/**
* just the title and a hashCode from instance will be the win ID
*/
private final String winId;
/**
* win pane contains title and content pane
*/
private final AnchorPane winPane = new AnchorPane();
/**
* title pane to add title label and some three [close-min-max] buttons maybe...
*/
private final AnchorPane titlePane = new AnchorPane();
/**
* where the content goes there ...
*/
private final AnchorPane content = new AnchorPane();
/**
* win title pane height
*/
private final int winTitlePaneH = 30;
/**
* three close-min-max buttons
*/
private final Circle closeShape = new Circle();
private final Circle minShape = new Circle();
private final Circle maxShape = new Circle();
/**
* initialize the win class with some important params
*
* @param root //where the win add to scene
* @param title // and String ID make by title+hashCode and used in windowManager
* @param winW //win width
* @param winH // win height
*/
public win(AnchorPane root, String title, int winW, int winH) {
//init some final vars
this.root = root;
this.winId = title + "--" + this.hashCode();
// make the winPane
winPane.setEffect(new DropShadow(20, rgb(0, 0, 0, 0.9)));
winPane.setPrefSize(winW, winH);
winPane.setStyle("-fx-background-color: #abcdef");
// put winPane center of scene
double screenW = Screen.getPrimary().getVisualBounds().getWidth();
double screenH = Screen.getPrimary().getVisualBounds().getHeight();
double deltaW = (screenW - winW) / 2;
double deltaH = (screenH - winH) / 2;
winPane.setLayoutX(deltaW);
winPane.setLayoutY(deltaH);
// put it to top on click
winPane.setOnMouseClicked(e -> {
winPane.toFront();
});
//make title and top of window ...
titlePane.setPrefHeight(winTitlePaneH);
AnchorPane.setTopAnchor(titlePane, 0.0);
AnchorPane.setLeftAnchor(titlePane, 0.0);
AnchorPane.setRightAnchor(titlePane, 0.0);
// make winPane draggable by titlePane
makeDragable(titlePane);
makeResizable(50);
// add close and min buttons to title pane
closeShape.setRadius(winTitlePaneH / 3);
closeShape.setFill(Color.RED); //red-yellow-green
closeShape.setOnMouseClicked(e -> {
closeShape.setFill(Color.BLACK);
e.consume();
});
//add min button to title pane
minShape.setRadius(winTitlePaneH / 3);
minShape.setFill(Color.YELLOW); //red-yellow-green
minShape.setOnMouseClicked(e -> {
minShape.setFill(Color.BLACK);
});
// add max button to title pane
maxShape.setRadius(winTitlePaneH / 3);
maxShape.setFill(Color.GREEN); //red-yellow-green
maxShape.setOnMouseClicked(e -> {
maxShape.setFill(Color.BLACK);
});
HBox bb = new HBox();
//bb.setBackground(new Background(new BackgroundFill(Color.BLACK, null, Insets.EMPTY)));
AnchorPane.setLeftAnchor(bb, 0d);
AnchorPane.setTopAnchor(bb, winTitlePaneH / 4.5);
AnchorPane.setBottomAnchor(bb, 0d);
bb.getChildren().addAll(closeShape, minShape, maxShape);
titlePane.getChildren().addAll(bb);
// add a label to show title
Label titleL = new Label(title);
titleL.setTextFill(Color.BLACK);
titleL.setAlignment(Pos.BASELINE_CENTER);
AnchorPane.setTopAnchor(titleL, 5.0);
AnchorPane.setLeftAnchor(titleL, 0.0);
AnchorPane.setRightAnchor(titleL, 0.0);
titlePane.getChildren().add(titleL);
titlePane.setBackground(new Background(new BackgroundFill(Color.web("#E2E0E2"), CornerRadii.EMPTY, Insets.EMPTY)));
winPane.getChildren().add(titlePane);
root.getChildren().add(winPane);
}
/**
* titlePane to drag and win move behavior
*
* @param what
*/
public void makeDragable(Node what) {
final Delta dragDelta = new Delta();
what.setOnMousePressed(mouseEvent -> {
dragDelta.x = winPane.getLayoutX() - mouseEvent.getScreenX();
dragDelta.y = winPane.getLayoutY() - mouseEvent.getScreenY();
//also bring to front when moving
winPane.toFront();
});
what.setOnMouseDragged(mouseEvent -> {
winPane.setLayoutX(mouseEvent.getScreenX() + dragDelta.x);
winPane.setLayoutY(mouseEvent.getScreenY() + dragDelta.y);
});
}
//current state
private boolean RESIZE_BOTTOM;
private boolean RESIZE_RIGHT;
public void makeResizable(double mouseBorderWidth) {
winPane.setOnMouseMoved(mouseEvent -> {
//local window's coordiantes
double mouseX = mouseEvent.getX();
double mouseY = mouseEvent.getY();
//window size
double width = winPane.boundsInLocalProperty().get().getWidth();
double height = winPane.boundsInLocalProperty().get().getHeight();
//if we on the edge, change state and cursor
if (Math.abs(mouseX - width) < mouseBorderWidth
&& Math.abs(mouseY - height) < mouseBorderWidth) {
RESIZE_RIGHT = true;
RESIZE_BOTTOM = true;
winPane.setCursor(Cursor.NW_RESIZE);
} else {
RESIZE_BOTTOM = false;
RESIZE_RIGHT = false;
winPane.setCursor(Cursor.DEFAULT);
}
});
winPane.setOnMouseDragged(mouseEvent -> {
//resize root
Region region = (Region) winPane;
//resize logic depends on state
if (RESIZE_BOTTOM && RESIZE_RIGHT) {
region.setPrefSize(mouseEvent.getX(), mouseEvent.getY());
} else if (RESIZE_RIGHT) {
region.setPrefWidth(mouseEvent.getX());
} else if (RESIZE_BOTTOM) {
region.setPrefHeight(mouseEvent.getY());
}
});
}
//just for encapsulation
private static class Delta {
double x, y;
}
}
Upvotes: 0
Views: 909
Reputation: 1781
Mouse click works perfectly fine on Circle
in JavaFX. The problem with your code is that the label you add for the title is on top of your circles and catches the mouse clicks. You can only click the circles on the very bottom which made you think that it works "sometimes". Check the image here:
So you can solve it by making the label mouse transparent with:
titleL.setMouseTransparent(true);
or adding first the label and then the HBox
with the circles.
For this kind of problems ScenicView comes really handy tool.
Upvotes: 2
Reputation: 587
I use a HBox to group and layout the three buttons [close min max] and then toFront() it. and they goes over title pane and now events work correctly...
Upvotes: 0