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();
}
}
Related
Lets say I have some TextField which is placed deep in the panes layout structure. I want add listener or recognize in some way that TextField changed its position (x, y) in Scene. The question is - how can I achive it in a proper, reusable way?
I provide some test code. To recreate please drag stage border, which will cause TextField position change.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
TextField textField = new TextField();
Button button = new Button("Button");
HBox hBox = new HBox(textField, button);
hBox.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
StackPane stackPane = new StackPane(hBox);
stackPane.setPrefSize(600., 400.);
Scene scene = new Scene(stackPane);
stage.setScene(scene);
stage.show();
}
}
Add a listener to the localToSceneTransform property of the node.
node.localToSceneTransformProperty().addListener((o, oldValue, newValue) -> {
System.out.println("transform may have changed");
});
Note that this
Yields some "false positives", i.e. it may notify you, if the position hasn't actually changed.
Registering too many of those listeners to nodes may decrease the performance of your application, since doing so involves listening to changes for all nodes in the hierarchy up to the root node.
In addition to this a listener to the boundsInLocal property may be needed, if you also want to be notified to the size of the node itself changing.
I have a problem with resizing a Stage with the sizeToScene method in javafx.
If I change the root node size above the maximum screen size and call sizeToScene, the window resizes well to the maximum possible screen size.
But if I recall sizeToScene, the scene becomes larger than the stage and the application is cut off.
Sometimes, the first call leads to the same behaviour as the last one described.
I don't know if it is a normal behavior and if there is a workaround solution to adjust the size of the scene to the size of the stage.
The same thing happened on linux and windows.
An example below
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class SceneSizeBug extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Button button = new Button("test");
button.setOnAction(e -> {
button.setPrefSize(2000, 2000);
primaryStage.sizeToScene();
});
button.setPrefSize(1280, 1024);
Scene s = new Scene(button, -1, -1);
primaryStage.setScene(s);
primaryStage.show();
}
}
Basically I am trying to make a short effect using JavaFX. I have the shape of a heart (added together from two circles and a polygon) that I can vary in size using the double value p. "Standart Size" would be p = 1.0;.
I am trying to add a pumping effect to the heart. I have the method pumpOnce():
public void pumpOnce(){
p = p + 1;
initHeart();
//Here goes what ever it takes to make stuff working!!
p = p - 1;
initHeart();
}
initHeart() draws the heart based on p.
I have found out that Thread.sleep(); or similar methods will not work due to the thread philosophy in JavaFX.
But what can I use instead?
The JavaFX animations are probably the way to go, but the "thread philosophy" in JavaFX isn't hard to work with if you want to roll your own, or do other, more complicated things in background threads.
The following code will pause and change the value in a label (full disclosure, I'm reusing code I wrote for another question):
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javax.xml.datatype.Duration;
public class DelayWithTask extends Application {
private static Label label;
public static void main(String[] args) { launch(args); }
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
label = new Label();
label.setText("Waiting...");
StackPane root = new StackPane();
root.getChildren().add(label);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
delay(5000, () -> label.setText("Hello World"));
}
public static void delay(long millis, Runnable continuation) {
Task<Void> sleeper = new Task<Void>() {
#Override
protected Void call() throws Exception {
try { Thread.sleep(millis); }
catch (InterruptedException e) { }
return null;
}
};
sleeper.setOnSucceeded(event -> continuation.run());
new Thread(sleeper).start();
}
}
The basic JavaFX background tool is the Task, any JavaFX application that actually does anything will probably be littered with these all over. Learn how to use them.
Dave's solution is great for general purpose off thread based work in JavaFX.
If you wish to use the animation facilities of JavaFX, the solutions below demonstrate this using a Timeline or a ScaleTransition. The timeline implements a discrete scale of the UI element, so every quarter of a second the UI element is scaled larger or back to it's original size. The scale transition implements a smooth scale of the UI element, so the UI element gradually gets larger then smaller using an interpolated scale factor with the default easing interpolator.
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
public class BeatingHeart extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
ImageView heart = new ImageView(HEART_IMAGE_LOC);
animateUsingTimeline(heart);
// animateUsingScaleTransition(heart);
StackPane layout = new StackPane(heart);
layout.setPrefWidth(heart.getImage().getWidth() * 2);
layout.setPrefHeight(heart.getImage().getHeight() * 2);
Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
private void animateUsingTimeline(ImageView heart) {
DoubleProperty scale = new SimpleDoubleProperty(1);
heart.scaleXProperty().bind(scale);
heart.scaleYProperty().bind(scale);
Timeline beat = new Timeline(
new KeyFrame(Duration.ZERO, event -> scale.setValue(1)),
new KeyFrame(Duration.seconds(0.5), event -> scale.setValue(1.1))
);
beat.setAutoReverse(true);
beat.setCycleCount(Timeline.INDEFINITE);
beat.play();
}
private void animateUsingScaleTransition(ImageView heart) {
ScaleTransition scaleTransition = new ScaleTransition(
Duration.seconds(1), heart
);
scaleTransition.setFromX(1);
scaleTransition.setFromY(1);
scaleTransition.setFromZ(1);
scaleTransition.setToX(1.1);
scaleTransition.setToY(1.1);
scaleTransition.setToZ(1.1);
scaleTransition.setAutoReverse(true);
scaleTransition.setCycleCount(Animation.INDEFINITE);
scaleTransition.play();
}
private static final String HEART_IMAGE_LOC =
"http://icons.iconarchive.com/icons/mirella-gabriele/valentine/128/Heart-red-icon.png";
// icon obtained from: http://www.iconarchive.com/show/valentine-icons-by-mirella-gabriele/Heart-red-icon.html
// icon license: Free for non-commercial use, commercial use not allowed.
}
I want to set Label to graphic. I tested this code:
private static final ImageView livePerformIcon;
static
{
livePerformIcon = new ImageView(MainApp.class.getResource("/images/Flex.jpg").toExternalForm());
}
final Label label = new Label();
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
livePerformIcon.setFitHeight(20);
livePerformIcon.setFitWidth(20);
label.setGraphic(livePerformIcon);
But I don't see any image.
The only way that I found to make it work is this:
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
Is there a way to solve this?
Not sure, but AFAIK controls should be created on the JavaFX Application thread, but you're creating ImageView in a static initializer, which I'm not sure if it's executed on the Application thread.
Besides: Do you really want livePerformIcon to be static???
This one made from the data used in the docs, works perfectly for me
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class LabelWithImages extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Label With Image Sample");
stage.setWidth(400);
stage.setHeight(180);
HBox hbox = new HBox();
//Replace the image you want to put up
Image image = new Image(getClass().getResourceAsStream("a.png"));
Label label = new Label("Demo Label");
label.setGraphic(new ImageView(image));
hbox.setSpacing(10);
hbox.getChildren().add((label));
((Group) scene.getRoot()).getChildren().add(hbox);
stage.setScene(scene);
stage.show();
}
}
Code snippets below will set the value of the property graphic of a label. You can use any of the two. I prefer using javafx css, just to implement the model-view-controller design.
// programmatically, provided with image input stream
label.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("path/to/image.png"))));
// javafx css, provided with image url
.label {
-fx-graphic: url("path/to/image.png");
}
Mouse handling on the SplitPane and ScrollBar controls breaks after displaying an application-modal Stage. The problem goes away after the application window loses and regains focus. Does anyone know a solution or workaround to this problem?
In what way is the mouse handling broken? When you click and start dragging on the control (SplitPane or ScrollBar), the control stops responding to your mouse movements the moment your mouse cursor leaves the control by a single pixel. This requires the user to be impossibly precise with the mouse. You would expect the control to respond to mouse movements, no matter where your mouse cursor happens to be, up until you release the mouse button.
The following code exhibits the problem on Ubuntu Linux and JRE 1.7.0_21. I have seen the problem on other JREs, but I have not tried another OS.
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.Modality;
public class SplitPaneBug extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button button = new Button(
"Move the SplitPane divider, then click here to show the modal"
+ " dialog.");
button.setOnAction(
new EventHandler() {
public void handle(Event event) {
Stage dialog = new ModalDialog();
dialog.showAndWait();
}
});
button.setMaxWidth(Double.MAX_VALUE);
SplitPane splitPane = new SplitPane();
splitPane.getItems().setAll(new BorderPane(), new BorderPane());
VBox vbox = new VBox();
vbox.getChildren().setAll(button, splitPane);
vbox.setVgrow(splitPane, Priority.ALWAYS);
primaryStage.setTitle("SplitPane Bug?");
primaryStage.setScene(new Scene(vbox, 640, 480));
primaryStage.show();
}
class ModalDialog extends Stage {
public ModalDialog() {
Button button = new Button(
"Click here to dismiss this dialog, then move the SplitPane"
+ " divider again.");
button.setOnAction(
new EventHandler() {
public void handle(Event event) {
close();
}
});
BorderPane borderPane = new BorderPane();
borderPane.setCenter(button);
initModality(Modality.APPLICATION_MODAL);
setTitle("Modal Dialog");
setScene(new Scene(borderPane, 600, 100));
sizeToScene();
}
}
}
Are you sure that you use 7u21? Please, set to output VersionInfo.getRuntimeVersion().
I don't reproduce on my ubuntu 12.10 with jdk 7u21(b11) downloaded from official site,
but there is known bug in fx 8.0 - https://javafx-jira.kenai.com/browse/RT-29576