I want to have transparent progressindicator, which is indefinite.
here is the code, it shows grey background state/scene.
i wanted fully transparent.
I tried following code, but it shows background stage which is not transparent.
package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
#Override
public void start(Stage stage) {
/*
*
* my css file content:
*
* .progress-indicator .indicator { -fx-background-color: transparent;
* -fx-background-insets: 0; -fx-background-radius: 0;
*
* } .progress-indicator { -fx-progress-color: green ; }
*
*
*
*/
Stage initStage = new Stage();
initStage.initStyle(StageStyle.TRANSPARENT);
ProgressIndicator loadProgress = new ProgressIndicator();
loadProgress.setSkin(null);
loadProgress.setPrefWidth(50);
VBox box = new VBox();
box.getChildren().add(loadProgress);
final Scene scene = new Scene(box, 150, 150);
scene.setFill(Color.TRANSPARENT);
initStage.setScene(scene);
scene.getStylesheets().add("application.css");
initStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
For modena.css (the default JavaFX look and feel definition in Java 8), a slight shaded background was introduced for all controls (and also to panes if a control is loaded).
You can remove this by specifying that the default background is transparent. This can be done by adding the following line to your application's CSS file:
.root { -fx-background-color: transparent; }
This is in addition to other settings you already have in your code to initialize the style of the stage and background fill of the scene.
stage.initStyle(StageStyle.TRANSPARENT);
scene.setFill(Color.TRANSPARENT);
Note: in the questions's sample code, an additional stage (initStage) is created instead of using the passed in stage for the start method. The passed in stage can be initialized, utilized and shown directly by your code rather than creating an additional initStage.
stage.initStyle(StageStyle.TRANSPARENT);
this is for hide the top bar ( minimize, Restore Down and close)
scene.setFill(Color.TRANSPARENT);
this is for the frame color ( you can replace TRANSPARENT with any color GREEN YELLOW RED BLUE ...) but for me I want glass view if you can understand me, and with different color so the solution is
primaryStage.setOpacity(0.2);
The number 0.2 is between 0 and 1. 0 is hidden and 1 is normal form but between the numbers transparent so choose your number and run your program and see if this is what you want there is this code for full screen.
primaryStage.setFullScreen(true);
and in the css file do this
.root { -fx-background-color:rgba(0,0,0,1); }
and you can change the color with changed the number in rgba(0,0,0,1)
This works for me.
Parent root = FXMLLoader.load(getClass().getResource("login.fxml"));
Scene scene = new Scene(root);
scene.setFill(Color.TRANSPARENT);
stage.setScene(scene);
stage.initStyle(StageStyle.TRANSPARENT);
stage.show();
U just need mainly 2 things:
scene.setFill(Color.TRANSPARENT);
stage.initStyle(StageStyle.TRANSPARENT);
Related
Let us have a JavaFX program with the scene graph Group -> Canvas. The root (Group) is put inside a Scene, and the Scene is attached to a Window, specifically a Stage.
Once the Window is displayed on screen, the user may resize the Window. The height and the width may be changed. However, there are usually some restrictions to how small the Window can be made. Notably the Window has a titlebar, and it has an associated minimum width. See also the picture below.
I suspect that the minimum width of the titlebar is platform-dependent and further depends on user settings of the platform. So a more-less general way of accessing the parameter is desirable.
Is it possible to generally access the minimum (stable) width of the titlebar of a Window? If so, how?
A picture to explain concisely which length I am looking for:
(In the picture, the Window could not be made any smaller in the horisontal dimension).
Here is a MWE for testing (please try to decrease the horisontal width as far as possible):
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.stage.Stage;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) {
Group group = new Group();
Canvas canvas = new Canvas(200, 200);
group.getChildren().add(canvas);
Scene scene = new Scene(group);
stage.setTitle("Title");
stage.setScene(scene);
stage.show();
//System.out.println(stage.getMinWidth()); // default is also 0.0
//stage.setMinWidth(0); // we can see that a lower value than the sought-for minimum value will not have an effect
}
public static void main(String[] args) {
launch();
}
}
I am trying to display the gridlines of a GridPane Scene in JavaFX, but they aren't being displayed despite calling setGridLinesVisible(true). What am I doing wrong?
I want to display the gridlines on my program's main menu, so I can tell where to place nodes on it. Unfortunately, when I run the program all that is displayed is a blank screen with a single button.
My MainMenu Class:
package screens;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
/**
* Creates the main menu Pane object and returns it.
* #author LuminousNutria
*/
public class MainMenu {
public MainMenu() {}
public Pane getPane() {
GridPane grid = new GridPane();
grid.setGridLinesVisible(true);
Button bttn = new Button("button");
grid.add(bttn, 2, 2);
return grid;
}
}
My Main Class:
package mainPackage;
import screens.*;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
/**
* Displays the Pane.
* #author LuminousNutria
*/
public class Main extends Application {
// create main menu Pane
private Pane mainMenu = new MainMenu().getPane();
// create Scene
private Scene scene = new Scene(mainMenu, 1600, 900);
#Override
public void start(Stage stage) {
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is Displayed:
JavaFX's GridPane class will only create as many points as is defined by the programmer when they set the position of an object on the grid.
For example, if an object is added to the grid with the x and y positions both equal to 0, then the grid will only have one (x, y) position, that being, (0, 0).
Also, even if the grid has many positions, unless the programmer sets the HGap and Vgapgrid attributes, all of the "positions" of the grid, will be on the same point in the window created by the program.
The issue was that I hadn't adjusted the HGap and VGap attributes, so the entire grid was clustered on just one point in the window. This made it impossible to see any lines.
Replacing the getPane() method with the below code allowed me to see the grid lines.
public Pane getPane() {
GridPane grid = new GridPane();
grid.setGridLinesVisible(true);
grid.setVgap(8);
grid.setHgap(8);
Button btn = new Button("button");
grid.add(btn, 5, 5);
return grid;
}
This is what was displayed once I had fixed my program.
So goal here is to use custom ScrollBar for ScrollPane without having trouble with layout when maximizing/minimizing window.
Consider example program:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Layout extends Application
{
#Override
public void start(Stage stage)
{
BorderPane main = new BorderPane();
main.setPrefSize(800, 600);
BorderPane center = new BorderPane(); // begin center
center.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
main.setCenter(center); // end center
BorderPane left = new BorderPane(); // begin left
ScrollPane pane = new ScrollPane();
pane.setFitToWidth(true);
Pane p1 = new Pane(); // child 1
p1.setPrefSize(200, 100);
p1.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));
this.makeResizable(p1);
Pane p2 = new Pane(); // child 2
p2.setPrefSize(200, 100);
p2.setBackground(new Background(new BackgroundFill(Color.BLUE, CornerRadii.EMPTY, Insets.EMPTY)));
this.makeResizable(p2);
VBox content = new VBox(10, p1, p2); // content in scroll pane
pane.setContent(content);
// replace normal bars
pane.setHbarPolicy(ScrollBarPolicy.NEVER);
pane.setVbarPolicy(ScrollBarPolicy.NEVER);
// with custom
ScrollBar sb = new ScrollBar();
sb.setOrientation(Orientation.VERTICAL);
sb.minProperty().bind(pane.vminProperty());
sb.maxProperty().bind(pane.vmaxProperty());
sb.visibleAmountProperty().bind(pane.heightProperty().divide(content.heightProperty()));
sb.managedProperty().bind(sb.visibleAmountProperty().lessThan(1.0)); // bar should be managed when it is needed (content too long)
sb.visibleProperty().bind(sb.managedProperty()); // and also visible only when managed
sb.valueProperty().bindBidirectional(pane.vvalueProperty());
left.setCenter(pane); // content
left.setRight(sb); // scroll bar
main.setLeft(left); //end left
Scene scene = new Scene(main);
stage.setScene(scene);
stage.show();
}
// Simple for testing
double prevY;
boolean dragging;
// Makes node resizable on drag.
private void makeResizable(Region region)
{
region.addEventFilter(MouseEvent.MOUSE_PRESSED, e ->
{
this.dragging = true;
region.setPrefHeight(region.getHeight());
this.prevY = e.getSceneY();
});
region.addEventFilter(MouseEvent.MOUSE_DRAGGED, e ->
{
if (!this.dragging) return;
region.setPrefHeight(region.getPrefHeight() + (e.getSceneY() - this.prevY));
this.prevY = e.getSceneY();
});
region.addEventFilter(MouseEvent.MOUSE_RELEASED, e -> this.dragging = false);
}
public static void main(String[] args)
{
launch(args);
}
}
It will produce GUI with ScrollPane on the left with a custom ScrollBar that appears when content (2 nodes p1 and p2) exceed bounds. In order to make it easy to test - both p1 and p2 are made resizable when dragging them with mouse (try it). While the ScrollBar appears and works as expected, there is a flaw in layout if we would start maximizing and minimizing window.
For example:
Start program
Resize content so ScrollBar appears, but not too
much (make it so that when you maximize it, it will be in bounds)
Maximize window - you will notice that bar might have disappeard, but "empty space" appears.
Now, if you would somehow make refresh (e.g by resizing content again), bar would disappear due to layout pass update.
Other bug:
Start program and maximize.
Resize content so it is still contained in maximized window, but is big enough that when you minimize, it will exceed bounds.
Minimize
Notice how ScrollBar is misplaced.
There are few other bugs if you would try other stuff, but all originate from the fact that when you maximize/minimize this happens (using 1st example):
ScrollBar is managed and visible (considering content exceeds).
Maximize
Window is resized layout is calculated (using old values - managed=true && visible=true)
Layout happens, everything is in place, all properties receive update, including sb.visibleAmountProperty() making ScrollBar set managed and visible to false (since they are bound, see code).
ScrollBar becomes invisible and unmanaged, but layout already happened, and will not re-run.
How do I make it work with window maximizing? How else could I bind ScrollBar so it doesn't break when maximizing? Please note that we talk about maximizing, not resizing (which works).
I found one workaround, but it doesn't seem like absolutely best thing to do, if there is more proper one - please share.
sb.managedProperty().addListener(e -> Platform.runLater(() -> content.requestLayout()));
Since this will be ran "later" (and since also on main thread which 1st should finish previous layout), this will cause relayout to happen.
Why is it not best? Well for one it would be called also when not really needed (while not maximizing) causing double layout (and we can't really resove this with some if statement).
I don't know how to compare all of the x and y of the circle objects on pane to those of the mouse. The problem Im working on asks me to to set it so the secondary click of the mouse removes a point when it is placed on it, I figure I can do this by comparing all of the distances of the circles coordinates and the mouse coordinates (using distance formula) to the radi of the circles. If one of the distances is less than the radi I would remove that circle. The problem is that I dont know how to call all of the points on the pane so I can compare them. This is the code I have so far to give you a better understanding of how the points are set up.
import javafx.scene.paint.Color;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Homework6 extends Application {
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create a pane and set its properties
Pane pane = new Pane();
//Circle circle1 = new Circle(7);
Circle[] circles = new Circle[0];
pane.setOnMouseClicked(e -> {
switch (e.getButton()) {
case PRIMARY:
Circle circle1 = new Circle(7);
circle1.setCenterX(e.getX());
circle1.setCenterY(e.getY());
pane.getChildren().add(circle1);
circle1.setFill(Color.WHITE);
circle1.setStroke(Color.BLACK);
case SECONDARY:
}
});
// Create a scene and place the pane in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("KeyEventDemo"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
pane.requestFocus(); // text is focused to receive key input
}
public static void main(String[] args) {
launch(args);
}
}
No need to do any computations! Method evt.getTarget() should already return the circle that has been clicked.
Have a look at Oracle's JavaFX tutorials to learn how to handle event.
It appears that there is no API call to calculate the width (in pixels) of a text string in Java FX 2.2. There have been suggestions of workarounds on other forums, but my efforts to create or find any code that returns the width of a String, either using the default font or otherwise, have failed. Any help would be appreciated.
If you are just measuring the default font without CSS:
Place the String to be measured in a Text object.
Get the width of the Text object's layout bounds.
If you need to apply CSS:
Place the String to be measured in a Text object.
Create a throwaway Scene and place the Text object in the Scene.
Take a snapshot of the Text (if you are using Java 7) or call applyCss for Java 8.
Get the width of the Text object's layout bounds.
This works because it forces a layout pass on the Text which calculates it's layout bounds.
The scene in step 2 is required because that is just the way the CSS processor works (it needs a node to be located in a Scene to be able to do its job). Definitely read the linked javadoc for applyCss if you want to understand the processing further.
Sample Code
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
// displays the width in pixels of an arbitrary piece of text.
public class MeasureText extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(Stage stage) throws Exception {
final Text text = new Text("XYZZY");
new Scene(new Group(text));
// java 7 =>
// text.snapshot(null, null);
// java 8 =>
text.applyCss();
final double width = text.getLayoutBounds().getWidth();
stage.setScene(new Scene(new Label(Double.toString(width))));
stage.show();
}
}
Sample program output (displays the width in pixels of an arbitrary piece of text):
How (if at all) would this change if the text was printed to a graphicscontext with a set font?
Apply the font to a text object containing the same message you will plot to the canvas. Unlike when you are measuring text plotted to the scene graph, items plotted to a canvas do not have CSS applied to them, so you don't need to place the Text object in a scene and have CSS applied to it before measuring the text. You can measure the layout bounds of your text object and it will be the same as the bounds of the text plotted within the canvas with the same font.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.*;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.text.*;
import javafx.stage.Stage;
// displays the width in pixels of an arbitrary piece of text (which has been plotted on a canvas).
public class MeasureText extends Application {
#Override
public void start(Stage stage) throws Exception {
final String msg = "XYZZY";
final Text text = new Text(msg);
Font font = Font.font("Arial", 20);
text.setFont(font);
final double width = text.getLayoutBounds().getWidth();
Canvas canvas = new Canvas(200, 50);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFont(font);
gc.fillText(msg, 0, 40);
stage.setScene(new Scene(
new VBox(new Label(Double.toString(width)), canvas))
);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I tried this:
Text theText = new Text(theLabel.getText());
theText.setFont(theLabel.getFont());
double width = theText.getBoundsInLocal().getWidth();
and it seems to be working fine.
This solution works up until java 8:
float width = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth("", gc.getFont());
float height = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().getFontMetrics(gc.getFont()).getLineHeight();
Those classes have since been removed and are not available in newer java version!
Bounds bounds = TextBuilder.create().text(text).font(font).build().getLayoutBounds();
double width=bounds.getWidth();
double height=bounds.getHeight();