I am creating an application in JavaFx, In which I want to do that if any child stage is getting opened then it should be opened in center of parent stage.
I am trying to do this using mystage.centerOnScreen() but it'll assign the child stage to center of screen, not the center of parent stage.
How can I assign the child stage to center of parent stage?
private void show(Stage parentStage) {
mystage.initOwner(parentStage);
mystage.initModality(Modality.WINDOW_MODAL);
mystage.centerOnScreen();
mystage.initStyle(StageStyle.UTILITY);
mystage.show();
}
You can use the parent stage's X/Y/width/height properties to do that. Rather than using Stage#centerOnScreen, you could do the following:
public class CenterStage extends Application {
#Override
public void start(final Stage stage) throws Exception {
stage.setX(300);
stage.setWidth(800);
stage.setHeight(400);
stage.show();
final Stage childStage = new Stage();
childStage.setWidth(200);
childStage.setHeight(200);
childStage.setX(stage.getX() + stage.getWidth() / 2 - childStage.getWidth() / 2);
childStage.setY(stage.getY() + stage.getHeight() / 2 - childStage.getHeight() / 2);
childStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
When you don't determine a size for the childStage, you have to listen for width and height changes as width and height is still NaN when onShown is called.
final double midX = (parentStage.getX() + parentStage.getWidth()) / 2;
final double midY = (parentStage.getY() + parentStage.getHeight()) / 2;
xResized = false;
yResized = false;
newStage.widthProperty().addListener((observable, oldValue, newValue) -> {
if (!xResized && newValue.intValue() > 1) {
newStage.setX(midX - newValue.intValue() / 2);
xResized = true;
}
});
newStage.heightProperty().addListener((observable, oldValue, newValue) -> {
if (!yResized && newValue.intValue() > 1) {
newStage.setY(midY - newValue.intValue() / 2);
yResized = true;
}
});
newStage.show();
Related
I don't know what to call my problem. I need to make it so that I can change the length of the elements in the horizontal "list" like this:
I did it, but in a very clumsy way. Please tell me how to do this better, for example, so that you can easily write code for several (3 or more) elements. Maybe there is some built-in JavaFX way to do this.
My code:
Main:
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Pane pane1 = new Pane();
pane1.setPrefWidth(100);
pane1.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
Pane pane2 = new Pane();
HBox.setHgrow(pane2, Priority.ALWAYS);
pane2.setBackground(new Background(new BackgroundFill(Color.GREEN, CornerRadii.EMPTY, Insets.EMPTY)));
MainPane root = new MainPane(pane1, pane2);
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MainPane:
public final class MainPane extends HBox {
private double mx;
public MainPane(Pane pane1, Pane pane2) {
getChildren().addAll(pane1, pane2);
setOnMouseMoved(mouseEvent -> {
if (mouseEvent.getSceneX() < pane1.getWidth() + 9 && mouseEvent.getSceneX() > (pane1.getWidth() - 6)) {
if (getCursor() != Cursor.H_RESIZE)
setCursor(Cursor.H_RESIZE);
} else if (getCursor() != Cursor.DEFAULT)
setCursor(Cursor.DEFAULT);
});
setOnMouseReleased(mouseEvent -> {
if (getCursor() == Cursor.H_RESIZE && !(mouseEvent.getSceneX() < pane1.getWidth() + 9 && mouseEvent.getSceneX() > (pane1.getWidth() - 6)))
setCursor(Cursor.DEFAULT);
});
setOnMousePressed(mouseEvent -> {
if (getCursor() == Cursor.H_RESIZE)
mx = mouseEvent.getSceneX() - (pane1.getWidth());
});
setOnMouseDragged(mouseEvent -> {
if (getCursor() == Cursor.H_RESIZE) {
double newPane1Width = mouseEvent.getSceneX() - mx;
double newPane2Width = pane2.getWidth() - newPane1Width + pane1.getWidth();
pane1.setPrefWidth(newPane1Width);
pane2.setPrefWidth(newPane2Width);
}
});
}
}
I have ArrayList<ImageView> imageViews = new ArrayList<>(); and so it contains images.
Images are created on button click, saved to that array and appears on scene from that array. Code is somewhat messy, but hey, #makeItWork at first #makeItRight later...
public void btnAddAndAction() throws FileNotFoundException {
algorithm.addElement(algorithm.calculateId(),"AND",null);
imageViews.add(new ImageView(algorithm.getLastElementImg()));
imageViews.get(imageViews.size()-1).setX(25); //default pos
imageViews.get(imageViews.size()-1).setY(85);
pane.getChildren().add( imageViews.get(imageViews.size()-1));
pane.requestLayout();
imageViews.get(imageViews.size()-1).setOnMousePressed(imgOnMousePressedEventHandler);
imageViews.get(imageViews.size()-1).setOnMouseDragged(imgOnMouseDraggedEventHandler);
}
//FIXME
EventHandler<MouseEvent> imgOnMousePressedEventHandler =
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
orgTranslateX = ((imageViews.get(imageViews.size()-1)).getTranslateX());
orgTranslateY = ((imageViews.get(imageViews.size()-1)).getTranslateY());
}
};
//FIXME
EventHandler<MouseEvent> imgOnMouseDraggedEventHandler =
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
double offsetX = t.getSceneX() - orgSceneX;
double offsetY = t.getSceneY() - orgSceneY;
double newTranslateX = orgTranslateX + offsetX;
double newTranslateY = orgTranslateY + offsetY;
(imageViews.get(imageViews.size()-1)).setTranslateX(newTranslateX);
(imageViews.get(imageViews.size()-1)).setTranslateY(newTranslateY);
}
};
I'm trying to do drag and drop feature to the images and I am struggling to detect what's under mouse...
I've fount getSource from MouseEvent, but it needs object...
so: how do I know, which element of array is pressed so I could drag it??
Java 1.8, JavaFX, IntelliJ.
Solution is to CAST ImageView... Answer is in the comment section.
I want to make an animation with the "width" of my node.
In this case my node is a "AnchorPane".
I try to make a navigation drawer in javafx.
there is no property "width Property ()"?
new Key Value (node.width Property (), 1, WEB_EASE)
node.widthProperty().getValue() not found
My code:
public void changeWidth(final Node node, double width) {
this.node = node;
this.timeline = TimelineBuilder.create()
.keyFrames(
new KeyFrame(Duration.millis(20),
new KeyValue( going here? , width, WEB_EASE)
)
)
.build();
setCycleDuration(Duration.seconds(5));
setDelay(Duration.seconds(0));
}
Example with "opacity" property:
new KeyValue(node.opacityProperty(), 1, WEB_EASE)
My class ConfigAnimationViewPane:
public class ConfigAnimationViewPane extends Transition {
protected static final Interpolator WEB_EASE = Interpolator.EASE_BOTH;
protected AnchorPane node;
protected Timeline timeline;
private boolean oldCache = false;
private CacheHint oldCacheHint = CacheHint.DEFAULT;
private final boolean useCache = true;
/**
* Called when the animation is starting
*/
protected void starting() {
if (useCache) {
oldCache = node.isCache();
oldCacheHint = node.getCacheHint();
node.setCache(true);
node.setCacheHint(CacheHint.SPEED);
}
}
/**
* Called when the animation is stopping
*/
protected void stopping() {
if (useCache) {
node.setCache(oldCache);
node.setCacheHint(oldCacheHint);
}
}
#Override protected void interpolate(double d) {
timeline.playFrom(Duration.seconds(d));
timeline.stop();
}
}
This is mi controller:
Move the menu to the left (the occult)
LeftTransition leftTransition = new LeftTransition();
leftTransition.OpenMenu(list1);
leftTransition.play();
Here I want to put my size "AnchorPane".
(Set the width of my "anchorpane")
/*ViewPaneTransition paneTransition = new ViewPaneTransition();
paneTransition.CloseMenu(viewPane, width );
paneTransition.play();*/
Here is a working example for java 9. It changes both the width and the height (just remove the height line if you don't need it)
The widthProperty is readOnly so yo have to set either maxWidth or minWidth switch the case you need.
the delay duration on timeline is 0 by default, no need to set it, and the cycleduration is computed from the keyframes durations.
public void changeSize(final Pane pane, double width, double height) {
Duration cycleDuration = Duration.millis(500);
Timeline timeline = new Timeline(
new KeyFrame(cycleDuration,
new KeyValue(pane.maxWidthProperty(),width,Interpolator.EASE_BOTH)),
new KeyFrame(cycleDuration,
new KeyValue(pane.maxHeightProperty(),height,Interpolator.EASE_BOTH))
);
timeline.play();
timeline.setOnFinished(event->{
/* insert code here if you need */
});
}
public void changeWidth(final Pane/*Region*/ node, double width) {//its a Pane or Regions
this.node = node;
this.timeline = TimelineBuilder.create()
.keyFrames(
new KeyFrame(Duration.millis(20),
new KeyValue( going here? , width, WEB_EASE)
)
)
.build();
setCycleDuration(Duration.seconds(5));
setDelay(Duration.seconds(0));
}
In this case my node is a "AnchorPane".
your AnchorPane is a subclass or Pane, let your wrappers or methods take in Pane or their respective class
guys! I am having an issue in my JavaFX Application. Images are able to be dragged and placed anywhere on the entire pane. This was working wonderfully, up until I added a second event handler. I added a second event handler to handle deletion. Right-clicking on the image gives you a pop up menu with deletion as an option. As soon as I added this, dragging stopped working properly. While it still works somewhat, the mouse is no longer ever on the image. As soon as you begin dragging, the image jumps over and down like 300 px? I am still able to drag, but I am not dragging on top of the image.
I understand this explanation isn't clear, and I can easily upload a gif of what happens if someone wants me to. Here's the code:
#FXML
private void handleImageButton()
{
System.out.println("Image Clicked");
closeMenus(6);
//contains the image path or image URL
String picURL = imageURL.getText();
if (!picURL.equals(""))
{
Image image = new Image(new File(picURL).toURI().toString());
ImageView iv = new ImageView();
iv.setImage(image);
iv.setCursor(Cursor.MOVE);
iv.setOnMousePressed(imageOnMousePressedEventHandler);
iv.setOnMouseDragged(imageOnMouseDraggedEventHandler);
workspace.getChildren().add(iv);
final ContextMenu contextMenu = new ContextMenu();
MenuItem delete = new MenuItem("Delete");
contextMenu.getItems().addAll(delete);
iv.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e){
if (e.isSecondaryButtonDown()){
contextMenu.show(workspace, e.getScreenX(), e.getScreenY());
delete.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event){
workspace.getChildren().remove(iv);
}
});
} //end if
}
});
}
}
EventHandler<MouseEvent> imageOnMousePressedEventHandler =
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (ImageTools.isVisible())
{
originalX = t.getSceneX();
originalY = t.getSceneY();
newX = ((ImageView)(t.getSource())).getTranslateX();
newY = ((ImageView)(t.getSource())).getTranslateY();
System.out.println("(" + newX + ", " + newY + ")");
}
}
};
EventHandler<MouseEvent> imageOnMouseDraggedEventHandler =
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (ImageTools.isVisible())
{
double offsetX = t.getSceneX() - originalX;
double offsetY = t.getSceneY() - originalY;
double newTranslateX = newX + offsetX;
double newTranslateY = newY + offsetY;
((ImageView)(t.getSource())).setTranslateX(newTranslateX);
((ImageView)(t.getSource())).setTranslateY(newTranslateY);
System.out.println("(" + newTranslateX + ", " + newTranslateY + ")");
}
}
};
The problem is that you are overriding your mouse listeners:
iv.setOnMousePressed(imageOnMousePressedEventHandler);
iv.setOnMouseDragged(imageOnMouseDraggedEventHandler);
iv.setOnMousePressed(new EventHandler() {});
setOnXYZ is a setter for a property, holding only one listener, so you are effectively overwriting your listeners in steps 1 and 3.
Use Node.addEventHandler() to add multiple handlers for the same EventType or in this case i would suggest using setOnContextMenuRequested to show the context menu because it is more convenient and system independent.
I am working on a project and I need you help.
I want to know that is this possible to set anchorpane constraints in percentage as something like
AnchorPane.setLeftAnchor(content1, 35%);
Yes it can be by updating constraint values on every scene size change:
public class AnchorDemo extends Application {
private final Button button = new Button("Add");
private final ListView list = new ListView();
#Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
AnchorPane.setTopAnchor(list, 10.0);
AnchorPane.setLeftAnchor(list, 10.0);
AnchorPane.setTopAnchor(button, 10.0);
AnchorPane.setRightAnchor(button, 10.0);
root.getChildren().addAll(list, button);
Scene scene = new Scene(root, 300, 250);
scene.widthProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
updateWidthConstaints(newValue.doubleValue());
}
});
primaryStage.setScene(scene);
primaryStage.show();
updateWidthConstaints(scene.getWidth());
}
private void updateWidthConstaints(double width) {
// roughly give to the list 66% while to the button 33% of available
// space, besides paddings.
// +5s are for extra padding
AnchorPane.setRightAnchor(list, width * 1 / 3 + 5);
AnchorPane.setLeftAnchor(button, width * 2 / 3 + 5);
}
public static void main(String[] args) {
launch(args);
}
}