Consider this:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.layout.FlowPaneBuilder;
import javafx.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageBuilder;
public class DualMonitorProblem extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage stage) throws Exception {
Label label = LabelBuilder.create().text("I seem to be lost").build();
Scene dlgScene = SceneBuilder.create().root(label).build();
final Stage dlgStage = StageBuilder.create().scene(dlgScene).resizable(false).build();
dlgStage.initModality(Modality.APPLICATION_MODAL);
dlgStage.initOwner(stage);
Button btn = ButtonBuilder.create().text("put me on secondary monitor before clicking me").build();
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
dlgStage.showAndWait();
}
});
Button btn2 = ButtonBuilder.create().text("me too").build();
btn2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
dlgStage.setX(stage.getX() + stage.getWidth() / 2);
dlgStage.setY(stage.getY() + stage.getHeight() / 2);
dlgStage.showAndWait();
}
});
Button btn3 = ButtonBuilder.create().text("me too").build();
btn3.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
dlgStage.centerOnScreen();
dlgStage.showAndWait();
}
});
Pane p = FlowPaneBuilder.create().children(btn, btn2, btn3).build();
Scene scene = SceneBuilder.create().root(p).width(800).height(600).build();
stage.setScene(scene);
stage.show();
}
}
Drag the stage to a secondary monitor and then click one of the buttons. When you do nothing extra the modal dialog will open on the primary monitor.
What is the easiest way to have the modal dialog open in the center of the parent stage? Stage.centerOnScreen() doesn't same to take into account a dual monitor setup. Should I consider this a bug and file it? Or is there another way to achieve this?
There a static method
static ObservableList<Screen> getScreens() The observable list of currently available Screens.
in Screen class. And
static Screen getPrimary() The primary Screen.
use them to determine, which screen is not a Primary.
You can use it to determine, which screens you have. And use Window. setX and setY methods - to position a window - just a simple math.
Also, I checked in JFX jira, that there are no features about adding any method method centering with a screen as parameter. So, you can file an RFE, to add method centerOnScreen(Screen)...
Related
I need remove my javafx app from the taskbar. I tried StageStyle.UTILITY. This is works but I need both UNDECORATED and UTILITY stage styles or another solvings.
Thank you for your replies.
Sorry you've been waiting so long for some sort of an answer on this, the following is mainly for people who come to this in the future hoping to discover a way of achieving this.
Let me start of by saying I wouldn't consider the following a solution but more of a workaround.
Assigning more than one initStyle to a stage is not possible however hiding the application from the task-bar and assigning an initStyle other than utility to the stage that is shown is.
To achieve this one must create two stages, the stage they want the user to see, and an another stage that will be considered the parent of the main stage and will be of initStyle.UTILITY this will prevent the icon from showing in the task-bar.
Below you can see the hello world example from oracles documentation modified to allow for an undecorated window with no icon (Note if one wanted to achieve a transparent/decorated window they could do so by changing the style of mainStage).
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class MultipleStageStyles extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.initStyle(StageStyle.UTILITY);
primaryStage.setOpacity(0);
primaryStage.setHeight(0);
primaryStage.setWidth(0);
primaryStage.show();
Stage mainStage = new Stage();
mainStage.initOwner(primaryStage);
mainStage.initStyle(StageStyle.UNDECORATED);
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
mainStage.setScene(new Scene(root, 300, 250));
mainStage.show();
}
}
I would like to have a webview component and a button on the stage but when I load a http://mail.google.com in the WebView the other button drawn on the stage gets problems.
After having loaded the page successfully if I hover on the button with the mouse the button itself disappears leaving only its label visible.
The problem is only on Linux since when I tried the same project with Windows it was okay.
The funny story is that if I change the url I want to load with another one, say http://www.google.com the button is not affected by this weird problem.
My Linux 64 bit Mint 17.3 and the Java version is jdk1.8.0_91.
Here is the code, a video and some screenshots of the strange behaviour.
package javafxwebviewnofxml;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
/**
*
* #author Aldo Marx
*/
public class JavaFXWebviewNoFXML extends Application {
public WebEngine webEngine;
public String urlToGo;
public AnchorPane anchorPane;
private WebView webView;
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Hello World my friends!");
}
});
anchorPane = new AnchorPane() ;
anchorPane.setPrefSize(1160, 900);
AnchorPane.setLeftAnchor(btn, 900.00);
AnchorPane.setTopAnchor(btn, 400.00);
webView = new WebView();
webView.setPrefSize(1160, 900);
webEngine = webView.getEngine();
urlToGo = "http://mail.google.com"; // this url is not okay
// urlToGo = " http://facebook.com"; // this url is okay
// urlToGo = "http://www.google.com"; // this url is okay
webEngine.load(urlToGo);
anchorPane.getChildren().addAll(webView);
anchorPane.getChildren().addAll(btn);
Scene scene = new Scene(anchorPane, 1160, 900);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The button as appears on the stage when it's not hovered by the mouse can be seen here below
The button as appears on the stage when it is hovered by the mouse (and this is the problem ) can be seen here below
I fixed the issue by adding -Dprism.order=j2d to VM options.
Don's set layout x, ... when placing in an AnchorPane, use anchoring: AnchorPane.setLeftAnchor and similar
I feel like I have searched half the Web and found no solution...
I have a java application displaying a Map(different countries etc.).
currently you are able to scroll down and up using your mouse wheel...
I want it so, that you are able to scroll sideways (horizontally).
All I need is a Listener (in Swing or Javafx does not matter) triggering whenever the mousewheel gets tilted, without the need for a focus of the map (hovering with your mouse should be enough the windows should still be focused) and without any visible scrollbars.
Using the following code every time you scroll sideways a message gets printed out...
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Scene;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
scene.setOnScroll(new EventHandler<ScrollEvent>(){
#Override
public void handle(ScrollEvent event) {
System.out.println("Scroll:" + event.getDeltaX());
}
});
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
One thing to consider:
Apparently when embedding a JFXPanel into a JFrame the sideway scrolling event is not getting passed.
I need either a Label or a Text for my project. I need the label so that ellipsis can be used. The problem though, is when I try to use a FadeTransition, and play it, the label gets slightly darker at the start. Here is some demo code:
package com.neonorb.test;
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
/**
* Created by chris on 7/20/15.
*/
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws IOException {
Label label = new Label("hello");
//Text label = new Text("hello);//Using Text instead of Label does not cause the weird behavior
FadeTransition fadeTransition = new FadeTransition(Duration.seconds(3), label);
fadeTransition.setFromValue(1.0);
fadeTransition.setToValue(0.0);
fadeTransition.setOnFinished(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
label.setOpacity(1.0);
}
});
Button button = new Button("play");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
fadeTransition.play();
}
});
BorderPane borderPane = new BorderPane();
borderPane.setCenter(label);
borderPane.setBottom(button);
primaryStage.setScene(new Scene(borderPane));
primaryStage.show();
}
}
So I either need a fix to this problem, or a way to use ellipsis in Text. Any ideas?
Set the opacity of the label to 0.99 initially:
label.setOpacity(0.99);
Also change the code inside setOnFinished method in the same way. Then, set the starting value of the fade transition to 0.99:
fadeTransition.setFromValue(0.99);
I know this is not the solution you are looking for, but this solution prevents the label from abruptly getting darker at the start. That is because the label actually starts with that darker status.
I created a little View and put them into a stage. I set the stage APPLICATION_MODAL:
stage.initModality(Modality.APPLICATION_MODAL);
If I click on the calling Window a blocking sound appears. So this is the right action.
But is there any posibility to replace this blocking sound, with an own function? I want to close the new stage if I click on the calling window, but I really tried all what comes to my mind, even an Eventfilter for Event.ANY doesn't work:
stage.addEventFilter(Event.ANY, new EventHandler<Event>() {
#Override
public void handle(Event event) {
System.out.println("Event catched: "+event);
}
});
Is there any way to handle the click on the calling window?
When you set something to APPLICATION_MODAL, you prevent any of the events from being dispatched to ANY window. This means that your event listener is of no use. Here is what the docs say:
APPLICATION_MODAL
Defines a modal window that blocks events from being
delivered to any other application window.
My suggestion is that you disable all your components when your custom view is visible and when a click occurs on the parent window while your view is visible, close your view. This will solve the problem of explicitly setting the modality (Anyways your events are not being passed).
SSCCE:
package stack;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFieldBuilder;
import javafx.scene.effect.Reflection;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextBuilder;
import javafx.stage.Modality;
import javafx.stage.Popup;
import javafx.stage.Stage;
import javafx.stage.StageBuilder;
public class DismissPopup extends Application {
Text hello;
Scene primaryScene;
TextField f;
Stage extraStage;
Scene extraScene;
#Override
public void start(Stage primaryStage) throws Exception {
primaryScene = SceneBuilder
.create()
.width(300)
.height(300)
.root(new StackPane())
.fill(Color.BLACK)
.build();
hello = TextBuilder
.create()
.text("Hello")
.effect(new Reflection())
.build();
f = TextFieldBuilder
.create()
.promptText("Enter Some Text")
.build();
extraScene = SceneBuilder
.create()
.width(300)
.height(300)
.root(new StackPane())
.fill(Color.WHEAT)
.build();
StackPane p = (StackPane) extraScene.getRoot();
p.getChildren().addAll(hello);
p = (StackPane) primaryScene.getRoot();
p.getChildren().addAll(f);
extraStage = StageBuilder
.create()
.scene(extraScene)
.build();
extraStage.sizeToScene();
primaryScene.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent me) {
if(f.disabledProperty().get() == false){
f.setDisable(true);
f.setText("The TextField is disabled");
extraStage.show();
}else{
f.setText("The TextField is enabled");
f.setDisable(false);
extraStage.close();
}
}
});
primaryStage.setScene(primaryScene);
primaryStage.sizeToScene();
primaryStage.show();
}
public static void main(String[] args) {
Application.launch("stack.DismissPopup");
}
}
Output: