I have a SplitPane and a Pane together in a stack. The Pane is underneath the SplitPane in the stack, and the middle SplitPane is a transparent AnchorPane. My intention is for an event to fire which draws a circle on the underlying Pane when I click somewhere within the area of the center pane, but I'm unable to get the event to fire by clicking on the pane.
(EDIT:This mouse event should come from the Pane, not from the anchorpane, because I also need the drawn shapes to respond to clicks.)
I have read posts on here about this and most solutions include MouseTransparent and PickOnBounds. I have tried what feels like every combination of those properties on the central AnchorPane, its label child, and the underlying Pane where the circle needs to be drawn to no avail. Any help is welcome! :)
Here are two images of both the physical layout and the hierarchy in scene builder. The blue showing is the underlying Pane. It is visible because the central AnchorPane is transparent.
Update: You can use setMouseTransparent(true/false) for the foreground split pane when entering/exiting the center anchor pane with the mouse like e. g. this:
Controller Class:
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
public class Controller {
#FXML
private Pane
backgroundPane;
#FXML
private SplitPane
foregroundSplitPane;
#FXML
public void handleBackgroundPaneOnMouseClick() {
// Create and add an ellipse:
Ellipse ellipse = new Ellipse();
ellipse.setRadiusX(50);
ellipse.setRadiusY(50);
ellipse.setFill(Color.BLACK);
ellipse.setLayoutX((backgroundPane.getWidth() / 2));
ellipse.setLayoutY((backgroundPane.getHeight() / 2));
backgroundPane.getChildren().add(ellipse);
}
#FXML
public void handleCenterAnchorPaneOnMouseEntered() {
foregroundSplitPane.setMouseTransparent(true);
}
#FXML
public void handleCenterAnchorPaneOnMouseExited() {
foregroundSplitPane.setMouseTransparent(false);
}
}
FXML File:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.StackPane?>
<StackPane prefHeight="150.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<Pane fx:id="backgroundPane" onMousePressed="#handleBackgroundPaneOnMouseClick" style="-fx-background-color: blue;" />
<SplitPane fx:id="foregroundSplitPane" dividerPositions="0.1, 0.9" style="-fx-background-color: rgba(255,255,255,0);">
<items>
<AnchorPane style="-fx-background-color: tomato;" />
<AnchorPane onMouseEntered="#handleCenterAnchorPaneOnMouseEntered" onMouseExited="#handleCenterAnchorPaneOnMouseExited" style="-fx-background-color: rgba(255,255,255,0);" />
<AnchorPane style="-fx-background-color: tomato;" />
</items>
</SplitPane>
</children>
</StackPane>
Preview:
Related
I'm trying to put two different buttons, one at the bottom left corner and another one to the bottom right corner.
These two buttons are in differents HBox and the two HBoxes are in the bottom of the Borderpane
To do that I did this, it works but it is ugly:
envoisButton = new Button("Envoyer la commande");
envoisButton.setStyle("-fx-font: 20px \"Roboto\";");
envoisButton.setPrefSize(300,50);
envoisButton.setGraphic(new ImageView(new Image("PleinVide/images/OK.png")));
HBox.setMargin(envoisButton,new Insets(0,20,20,20));
HBox rightButtons = new HBox(envoisButton);
rightButtons.setAlignment(Pos.CENTER_RIGHT);
synchroButton = new Button("Synchroniser");
synchroButton.setStyle("-fx-font: 20px \"Roboto\";");
synchroButton.setPrefSize(300,50);
synchroButton.setGraphic(new ImageView(new Image("PleinVide/images/synchronize.png")));
HBox.setMargin(synchroButton,new Insets(0,20,20,20));
HBox leftButtons = new HBox(synchroButton);
leftButtons.setAlignment(Pos.CENTER_LEFT);
HBox buttons = new HBox(leftButtons,rightButtons);
buttons.setSpacing(primaryScreenBounds.getWidth()*0.65); //This is very ugly (primaryScreenBounds == my screen resolution)
borderPane.setBottom(buttons);
Here's the result:
We can see that the 2 buttons are where I want them to be, but if in the future I want to add another button, this will not work at all :/
Do you have a solution to place the two buttons at the corners?
Thank you very much.
Wrap the two HBoxes in another HBox, set the appropriate alignments, and have them both always grow horizontally.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane(new Label("Hello, World!"));
HBox leftBox = new HBox(new Button("Left Button"));
leftBox.setAlignment(Pos.CENTER_LEFT);
HBox.setHgrow(leftBox, Priority.ALWAYS);
HBox rightBox = new HBox(new Button("Right Button"));
rightBox.setAlignment(Pos.CENTER_RIGHT);
HBox.setHgrow(rightBox, Priority.ALWAYS);
HBox bottom = new HBox(leftBox, rightBox);
bottom.setPadding(new Insets(10));
root.setBottom(bottom);
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.show();
}
}
Another option is to use a single HBox and use a "filler" region/pane. For example:
HBox hbox = new HBox();
hbox.getChildren().add(new Button("Left Button"));
Pane filler = new Pane();
hbox.getChildren().add(filler);
HBox.setHgrow(filler, Priority.ALWAYS);
hbox.getChildren().add(new Button("Right Button"));
borderPane.setBottom(hbox);
I would suggest
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<center>
<Pane style="-fx-background-color: red;" BorderPane.alignment="CENTER" />
</center>
<bottom>
<AnchorPane maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" style="-fx-background-color: green;" BorderPane.alignment="CENTER">
<children>
<Button text="Button" AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="20.0" />
<Button text="Button" AnchorPane.bottomAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="20.0" />
</children>
</AnchorPane>
</bottom>
</BorderPane>
you could use a gridpane.
Either instead of adding buttons in your example, add a gridpane, and add the buttons in that gridpane.
Or
Use a gridpane as your scene and style and add constraints accordingly (this is more difficult). This way if you want to add buttons, all you need to do is figure out the coordinates for the slots in the gridpane.
I have a fontawesomeicon. If I press the button btStart a red circle should flash on the Fontawesomeicon (see GIF). If I press the button btStop it should be disabled.
I tried it with a label.
When I press the button btStart, the label changes in a time interval with SetVisible(true) and setVisible(false).
Can someone offer me a solution? Thank you in advance.
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller.java
package sample;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import java.awt.*;
public class Controller {
#FXML
private FontAwesomeIconView iconCamera;
#FXML
private Button btStart;
#FXML
private Button btStop;
#FXML
void mouseCklicked(ActionEvent event) {
System.out.println("sad");
}
}
sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane alignment="center" hgap="10" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.141" fx:controller="sample.Controller">
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
<children>
<AnchorPane prefHeight="387.0" prefWidth="573.0">
<children>
<FontAwesomeIconView fx:id="iconCamera" glyphName="VIDEO_CAMERA" layoutX="130.0" layoutY="123.0" size="36" />
<Button layoutX="253.0" layoutY="93.0" mnemonicParsing="false" onAction="#mouseCklicked" text="Start" />
<Button layoutX="354.0" layoutY="93.0" mnemonicParsing="false" text="Stop" />
</children>
</AnchorPane>
</children>
</GridPane>
Create an Image (PNG) without the red dot.
Create a GIF with the red dot blinking effect.
Import both images in to your project.
On pressing the start set the image to *.GIF.
On pressing stop set the image to *.PNG.
Simple. Don't make things complicated!
I have the following FXML view:
VBox
ScrollPane
VBox buttonsContainer
Button (Adds a new button to buttonsContainer)
I want the ScrollPane to expand its height to match its child vbox's height, until it reaches a certain height [200px for example] then it stops expanding.
I've been playing around for the past 1 hour with the Min/Pref Viewport Height, and Min/Max/Pref Height properties to achieve this, but nothing worked out.
Is this this possible to do?
Edit: Here's a minimal, complete, and verifiable example :
MainView.fxml
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.VBox?>
<VBox alignment="CENTER" prefHeight="0.0" prefWidth="200.0" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MainController">
<ScrollPane maxHeight="200.0" VBox.vgrow="ALWAYS">
<VBox fx:id="_buttonsContainer" />
</ScrollPane>
<Button fx:id="_btnAddButton" mnemonicParsing="false" text="Button" />
</VBox>
MainController.java
public class MainController implements Initializable{
#FXML private Button _btnAddButton;
#FXML private VBox _buttonsContainer;
#Override
public void initialize(URL location, ResourceBundle resources) {
_btnAddButton.setOnAction(e -> {
addButton();
});
}
private void addButton(){
_buttonsContainer.getChildren().add(new Button());
}
}
This seems to work:
<ScrollPane fx:id="scrollPane" maxHeight="200.0" minViewportHeight="0.0" minHeight="0.0">
<VBox fx:id="_buttonsContainer" />
</ScrollPane>
The scroll pane, and its viewport, seem to have some fixed positive minimum height by default.
ScrollPane.prefHeightProperty().bind(VBox.heightProperty());
then add ScrollPane.setMaxHeight(200); try this
I've developed an application using JavaFX that, in part, uses a WebView. However, I've noticed that when either by the user or programmatically via JS, the WebView is scrolled to the bottom or just near the bottom, strange things seem to happen. I am specifically hoping for some way to stop this behavior, and still need to allow scrolling in both senses. It's similar to this question but they are not the same. The rest of my post explains what is happening.
If you scroll to the bottom and resize the window to be larger than previously and hover over other JavaFX controls in the window, they become white boxes.
To illustrate, suppose you have the following window:
Scroll to the bottom and resize the window to be larger than previously and then hover over the JavaFX button and TextBox, who both disappear when you do so:
This happens on at least Windows 10 with Java8u111 and Java8u51. I've made an example to demonstrate this:
example.Main.java
package example;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(Main.class.getResource("Example.fxml"));
BorderPane rootWindow = (BorderPane) loader.load();
Scene scene = new Scene(rootWindow);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
example.ExampleController.java
package example;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
public class ExampleController {
#FXML private WebView webView;
#FXML
private void initialize() {
WebEngine engine = webView.getEngine();
engine.load("https://stackoverflow.com");
engine.getLoadWorker().stateProperty().addListener( (o, oldVal, newVal) -> {
if (newVal == Worker.State.SUCCEEDED) {
engine.executeScript("window.scrollTo(0, document.body.scrollHeight);");
}
});
}
}
example.Example.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.web.WebView?>
<BorderPane prefHeight="400.0" prefWidth="500.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="example.ExampleController">
<center>
<WebView fx:id="webView" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</BorderPane.margin>
</WebView>
</center>
<bottom>
<HBox BorderPane.alignment="CENTER">
<children>
<TextField HBox.hgrow="ALWAYS" />
<Button alignment="TOP_LEFT" mnemonicParsing="false" text="Button" />
</children>
</HBox>
</bottom>
</BorderPane>
Is there a way I can stop this from happening or at least mitigate it?
I also encountered the same problem, and I found a solution:
Add a parameter to jvm:-Dprism.order=sw
see:https://news.kynosarges.org/2016/04/09/javafx-and-java_tool_options/?tdsourcetag=s_pctim_aiomsg
I need help inserting objects in a TilePane (contained within a ScrollPane) horizontally. It inserts horizontally until it reaches the end of the ScrollPane then starts adding to the next row of the ScrollPane. This is what it looks like:
The box is the ScrollPane and the TilePane is what is holding all the images.
Basically, I want the TilePane to keep adding to the right and have the ScrollPane show a horizontal scrollbar.
Here's my code:
private void start()
{
#FXML private ImageView bigImage;
#FXML private ScrollPane scrollPane;
#FXML private TilePane tilePane;
// Setup scrollpane
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
tilePane.setHgap(15);
for(int i = 0; i < 10; i++)
{
ImageView imageView = new ImageView(bigImage.getImage());
imageView.setFitWidth(100);
imageView.setFitHeight(100);
tilePane.getChildren().add(imageView);
}
//scrollPane.setFitToWidth(true);
scrollPane.setContent(tilePane);
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.TilePane?>
<AnchorPane prefHeight="700.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.PhotoController">
<children>
<ImageView fx:id="bigImage" fitHeight="441.0" fitWidth="534.0" layoutX="35.0" layoutY="52.0" pickOnBounds="true">
<image>
<Image url="#../../../../../../Pictures/Wallpaper02.jpg" />
</image>
</ImageView>
<ScrollPane fx:id="scrollPane" layoutX="35.0" layoutY="528.0" prefHeight="140.0" prefWidth="820.0">
<content>
<TilePane fx:id="tilePane" prefHeight="137.0" prefWidth="817.0" />
</content>
</ScrollPane>
</children>
</AnchorPane>
How can I accomplish what I want to do? Any help would be appreciated. Thank you!
you can use the ccs property "repeat" with your background like this, it will do all the work :
-fx-background-image:url("Image.png");
-fx-background-repeat:repeat;
For more modification looks in the Docs with the background properties.