How to reduce button click area (only to the button) - java

I've got a simple password generator in JavaFX. Whenever I click the button, a password is generated but also when I click somewhere else in the application area, the button also reacts. How can I reduce the click area?
Main
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("/sample/main.fxml"));
primaryStage.setTitle("Password Generator");
primaryStage.setScene(new Scene(root, 600, 400));
primaryStage.setMaxWidth(610.0);
primaryStage.setMaxHeight(450.0);
primaryStage.setMinWidth(600.0);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Main.fxml
<Pane fx:id="mainPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="416.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onMouseClicked="#generatePassword" prefHeight="417.0" prefWidth="600.0" style="-fx-background-color: #ed801a;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button fx:id="generatePassword" layoutX="206.0" layoutY="216.0" mnemonicParsing="false" onMouseClicked="#generatePassword" prefHeight="59.0" prefWidth="188.0" text="Generate">
<font>
<Font name="System Italic" size="20.0" />
</font>
</Button>
</children>
</AnchorPane>
</children>
</Pane>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onMouseClicked="#generatePassword" prefHeight="417.0" prefWidth="600.0" style="-fx-background-color: #ed801a;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
Remove the onMouseClicked="#generatePassword" from the AnchorPane declaration.

Related

JavaFX: expanding TextArea, Listview (Vgrow/Hgrow = 'ALWAYS' doesn't work)

I have a simple JavaFX application, a BorderLayout with an AnchorPane and inside two panes, one contains a HBox and a VBox with a TextArea and a ListView. I would like them to increase in width, as I increase the window size. I have tried Vgrow/Hgrow = 'ALWAYS' and Max Width/Max Height = 'MAX_VALUE' on the the controls but nothing works.- (I use Scene Builder to create the fxml)
The FXML is the following:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<BorderPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1">
<center>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" BorderPane.alignment="CENTER">
<children>
<Pane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
<Pane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="200.0">
<children>
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0">
<children>
<VBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" HBox.hgrow="ALWAYS">
<children>
<TextArea maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" VBox.vgrow="ALWAYS" />
<ListView maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" VBox.vgrow="ALWAYS" />
</children>
</VBox>
</children>
</HBox>
</children>
</Pane>
</children>
</AnchorPane>
</center>
</BorderPane>
My java application class (HelloApplication):
package com.example.demo;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
UPDATE: I removed the unnecessary AnchorPane and other Panes, kept only a VBox and placed it in another BorderLayout, take a look, now seems perfect :)
Don't hard-code sizes, and don't use layout panes such as Pane and AnchorPane that rely on hard-coded sizes except in very rare circumstances.
(You may sometimes need to set the max size to Double.MAX_VALUE to allow a control to grow beyond its preferred size, but even that is not necessary in this example, as far as I can tell.)
Your FXML has an empty Pane and at least two redundant wrapper containers which only wrap one node (the other Pane and the AnchorPane). Remove all of these and the hard-coded values and it will work:
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.*?>
<BorderPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1">
<center>
<HBox>
<children>
<VBox HBox.hgrow="ALWAYS">
<children>
<TextArea VBox.vgrow="ALWAYS" />
<ListView VBox.vgrow="ALWAYS" />
</children>
</VBox>
</children>
</HBox>
</center>
</BorderPane>
Depending on your real use-case, you may not need the HBox either:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.*?>
<BorderPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1">
<center>
<VBox>
<children>
<TextArea VBox.vgrow="ALWAYS" />
<ListView VBox.vgrow="ALWAYS" />
</children>
</VBox>
</center>
</BorderPane>

Components won't auto-resizing when using JFXDecorator, how to fix that?

I want to use JFXDecorator to fancy a look of a Window of my application. But using it brokes an auto-resize of components. This is what my code looks like
#Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ApplicationView.fxml"));
Parent root = loader.load();
JFXDecorator decorator = new JFXDecorator(stage, root);
decorator.setCustomMaximize(true);
stage.setTitle("Weather API");
stage.setScene(new Scene(decorator));
String cssURI = getClass().getResource("stylesheet/style.css").toExternalForm();
decorator.getStylesheets().add(cssURI);
stage.show();
}
And this is the effect, look at the split-pane.
Without JFXDecorator works normally with code like below.
#Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ApplicationView.fxml"));
Parent root = loader.load();
stage.setTitle("Weather API");
stage.setScene(new Scene(root));
String cssURI = getClass().getResource("stylesheet/style.css").toExternalForm();
stage.show();
}
I tried to set AncorPane properties of main pane similar to childs so maybe it will resising but it failed. My FXML looks like that
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="480.0" prefWidth="640.0" stylesheets="#stylesheet/style.css" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.161">
<children>
<SplitPane dividerPositions="0.29797979797979796" layoutX="220.0" layoutY="129.0" prefHeight="480.0" prefWidth="640.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
</items>
</SplitPane>
</children>
</AnchorPane>
How can I fix it? Thank You.
Get rid of the AnchorPane and make the SplitPane the root node.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<SplitPane dividerPositions="0.29797979797979796" prefHeight="480.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
</items>
</SplitPane>

JavaFX change scenes maintaining full screen

I'm trying to change from one screen to another in full screen model but only the first screen is on full screen, when I change to another screen the full screen dosn't work.
Here's my code:
Main
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setFullScreen(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
sample.fmxl
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<StackPane prefHeight="200.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="First Screen" textAlignment="CENTER" />
</children>
</HBox>
</children>
</StackPane>
<StackPane layoutY="163.0" prefHeight="200.0" prefWidth="600.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<HBox alignment="CENTER" prefHeight="200.0" prefWidth="600.0">
<children>
<Button fx:id="next" mnemonicParsing="false" onAction="#nextScreen" text="Next" />
</children>
</HBox>
</children>
</StackPane>
</children>
</AnchorPane>
FirstScreenController
public class Controller implements Initializable {
#FXML
private Button next;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
public void nextScreen(ActionEvent actionEvent) throws Exception {
SecondScreenController secondScreen = new SecondScreenController();
Stage stage = (Stage) next.getScene().getWindow();
stage.setFullScreen(true);
secondScreen.start(stage);
}
public void start(Stage window) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene scene = new Scene(root);
window.setScene(scene);
window.show();
}
}
sample2.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.SecondScreenController">
<children>
<StackPane prefHeight="200.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Second Screen" textAlignment="CENTER" />
</children>
</HBox>
</children>
</StackPane>
<StackPane layoutY="163.0" prefHeight="200.0" prefWidth="600.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<children>
<HBox alignment="CENTER" prefHeight="200.0" prefWidth="600.0">
<children>
<Button fx:id="back" mnemonicParsing="false" onAction="#backScreen" text="Back" />
</children>
</HBox>
</children>
</StackPane>
</children>
</AnchorPane>
SecondScreenController
public class SecondScreenController implements Initializable {
#FXML
private Button back;
#Override
public void initialize(URL location, ResourceBundle resources) {
}
public void start(Stage window) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("sample2.fxml"));
Scene scene = new Scene(root);
window.setScene(scene);
window.show();
}
public void backScreen(ActionEvent actionEvent) throws Exception {
Controller firstScreen = new Controller();
Stage stage = (Stage) back.getScene().getWindow();
stage.setFullScreen(true);
firstScreen.start(stage);
}
}
When I press the button Full Screen mode stop working, even if I go back to the first screen. Any idea how to solve this?
Add a window.setFullScreen(true); in SecondScreenController.java before window.show();.
Also add window.setFullScreen(true); in Controller.java in start() before window.show();

SplitPane Divider Position changes on its own

I have a SplitPane that is behaving strangely. It is "spontaneously" moving without interaction from the user.
Here is the sample FXML layout:
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<children>
<SplitPane fx:id="splitPane" dividerPositions="0.29797979797979796" layoutX="100.0" layoutY="67.0" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
</items>
</SplitPane>
</children>
</AnchorPane>
And the controller:
public class Controller {
#FXML
private SplitPane splitPane;
#FXML
private void initialize() {
// Add Listener to the divider value
splitPane.getDividers().get(0).positionProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("newValue = " + newValue);
});
splitPane.getDividers().get(0).setPosition(0.80);
}
}
Here I set the listener on the only divider to output it's current value when it changes. Just below, I set it to 0.80.
Here is the output:
newValue = 0.8
newValue = 0.7986577181208053
You see it does change after initially setting it. While this change is minimal in the example, the problem is exacerbated in my main application.
I am trying to save the divider's position between runs of my program, but with the position value changing on its own every time, the minor issue becomes a major one.
What is happening here and how can I prevent it from changing? Per the FXML, you can see there are no other controls that should be forcing a change due to minimum width, etc.

JavaFx custom components with Spring

I'm currently trying to create custom components in JavaFx for my desktop app, and I would like to use Spring DI.
I have read about how to make extendable components and without Spring I can do it, based on this code https://github.com/matrak/javafx-extend-fxml.
But when I replace the FXMLLoader with a custom SpringFXMLLoader it can't load the components.
In the main window, there is a button and a editbox, and on click I woul'd like to create a new custom module, with the given name. But it says, that the label in the custom component is null.
What am I doing wrong?
BasicModule.class
#org.springframework.stereotype.Controller
#DefaultProperty(value = "extension")
public class BasicModule extends BorderPane {
public Label label;
public AnchorPane extension;
public BasicModule() {
super();
}
public ObservableList<Node> getExtension() {
return extension.getChildren();
}
}
BasicModule.fxml
<fx:root type="javafx.scene.layout.BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.akos.fxmlTest.BasicModule">
<top>
<Label fx:id="label" text="Label Basic" BorderPane.alignment="CENTER"/>
</top>
<center>
<AnchorPane fx:id="extension" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER"/>
</center>
</fx:root>
CustomModule.class
public class CustomModule extends BasicModule {
#FXML
public Label customModuleLabel;
public void setText(String text) {
customModuleLabel.setText(text);
}
}
CustomModule.fxml
<fx:root type="com.akos.fxmlTest.BasicModule" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.akos.fxmlTest.CustomModule">
<Label fx:id="customModuleLabel" text="asdasdasdasd"/>
</fx:root>
Main.class
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfiguration.class);
context.getBeanFactory().registerResolvableDependency(Stage.class, primaryStage);
SpringFxmlLoader loader = context.getBean(SpringFxmlLoader.class);
Parent parent = (Parent) loader.load("/fxml/main.fxml");
primaryStage.setScene(new Scene(parent, 1000, 600));
primaryStage.setTitle("test");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
main.fxml
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.akos.fxmlTest.Controller">
<center>
<VBox fx:id="itemList" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets left="50.0" right="50.0" />
</BorderPane.margin>
</VBox>
</center>
<left>
<VBox prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
<children>
<Button fx:id="addButton" mnemonicParsing="false" onAction="#addNewModule" text="Button" />
<TextField fx:id="moduleNameEdit" />
</children>
</VBox>
</left>
</BorderPane>
Controller.class
#org.springframework.stereotype.Controller
public class Controller {
public VBox itemList;
public Button addButton;
public TextField moduleNameEdit;
public void addNewModule(ActionEvent actionEvent) {
CustomModule customModule = new CustomModule();
itemList.getChildren().add(customModule);
customModule.setText(moduleNameEdit.getText());
}
}
AppConfiguration.class
#Configuration
#ComponentScan("com.akos.fxmlTest")
public class AppConfiguration {}
Sorry for the wall of text.

Categories

Resources