JavaFx add Window-Control-Buttons to Menubar (IntelliJ like) - javafx

Since IntelliJ version 2019.2 Jetbrains removed the titlebar from the IDE and put the minimize, maximize and close button of the window into the menubar. So far, I have not found out how to do so using javafx. Is there a way to instanciate a "WindowControlButtons"-Class, so I can easily add them to the menubar or do I have to add a buttongroup and style the buttons for each platform myself?
Example how it shall look like on Windows:

As suggested by #mr mcwolf You can try below solution.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class JavaFXApplication1 extends Application {
#Override
public void start(Stage primaryStage) {
Button closeButton = new Button();
closeButton.setText("X");
closeButton.setOnAction((ActionEvent event) -> {
javafx.application.Platform.exit();
});
Button hideButton = new Button();
hideButton.setText("-");
hideButton.setOnAction((ActionEvent event) -> {
primaryStage.setIconified(true);
});
Menu menu = new Menu("Menu");
MenuItem menuItem1 = new MenuItem("item 1");
MenuItem menuItem2 = new MenuItem("item 2");
menu.getItems().add(menuItem1);
menu.getItems().add(menuItem2);
MenuBar menuBar = new MenuBar();
menuBar.getMenus().add(menu);
HBox hBox = new HBox(menuBar, hideButton, closeButton);
HBox.setHgrow(menuBar, Priority.ALWAYS);
HBox.setHgrow(hideButton, Priority.NEVER);
HBox.setHgrow(closeButton, Priority.NEVER);
BorderPane root = new BorderPane();
root.setTop(hBox);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Output on Windows looks like this.

Related

Why cursor resets to default after scene switch in JavaFX?

I know that I can set cursor type for the entire scene using Scene.setCursor method. But if I swap the scene with another one, cursor always resets to default - disregarding the cursor set on new scene. Here's the test case, tested in XFCE and XMonad:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HideCursor extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
root.setStyle("-fx-background-color: green");
Scene scene = new Scene(root, 600, 600);
scene.setCursor(Cursor.MOVE);
StackPane root2 = new StackPane();
root2.setStyle("-fx-background-color: blue");
Scene scene2 = new Scene(root2, 600, 600);
scene2.setCursor(Cursor.MOVE);
primaryStage.setScene(scene);
Button switchScene = new Button("switch");
root.getChildren().add(switchScene);
switchScene.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
primaryStage.setScene(scene2);
}
});
primaryStage.show();
}
}
Interestingly, in Windows 7 it works as expected. What am I doing wrong?

How to show ProgressIndicator in center of Pane in Javafx

I have a Pane with some controls and a button. When I click on the button, I want show ProgressIndicator in center of pane without removing any controls.
When I am adding a ProgressIndicator to pane during onAction of button, it adds it below the button. I want it to overlay on the pane.
The picture below explains what I want.
Code
package fx;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage arg0) throws Exception {
final VBox bx = new VBox();
bx.setAlignment(Pos.CENTER);
TextField userName = new TextField("User Name");
userName.setMaxWidth(200);
TextField email = new TextField("Email");
email.setMaxWidth(200);
Button submit = new Button("Submit");
submit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
ProgressIndicator pi = new ProgressIndicator();
//adding here but it is adding at below of button
//how to do here
bx.getChildren().add(pi);
//Further process
}
});
bx.getChildren().addAll(userName, email, submit);
Scene c = new Scene(bx);
arg0.setScene(c);
arg0.setMinWidth(500);
arg0.setMinHeight(500);
arg0.show();
}
public static void main(String[] args) {
Main h = new Main();
h.launch(args);
}
}
You need to use a StackPane as your root layout instead of using a VBox. StackPane allows you to stack nodes on top of each other (z-order).
On the button's action you can create a new ProgressIndicator and add it to your StackPane. I have introduced another VBox as the parent to the indicator, because I did not want the indicator to capture all the available space. You can disable the already present VBox to get the greying effect on button's action after the process is done you can enable the VBox again.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage arg0) throws Exception {
StackPane root = new StackPane();
VBox bx = new VBox();
bx.setAlignment(Pos.CENTER);
TextField userName = new TextField("User Name");
userName.setMaxWidth(200);
TextField email = new TextField("Email");
email.setMaxWidth(200);
Button submit = new Button("Submit");
submit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
ProgressIndicator pi = new ProgressIndicator();
VBox box = new VBox(pi);
box.setAlignment(Pos.CENTER);
// Grey Background
bx.setDisable(true);
root.getChildren().add(box);
}
});
bx.getChildren().addAll(userName, email, submit);
root.getChildren().add(bx);
Scene c = new Scene(root);
arg0.setScene(c);
arg0.setMinWidth(500);
arg0.setMinHeight(500);
arg0.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX Resizing TextField with Window

In JavaFX, how do I create a textfield inside an hbox (BorderPane layout) resize in width/length as the user resizes the window?
You can set the HGROW for the textfield as Priority.ALWAYS.
This will enable the TextField to shrink/grow whenever the HBox changes its width.
MCVE :
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField();
HBox container = new HBox(textField);
container.setAlignment(Pos.CENTER);
container.setPadding(new Insets(10));
// Set Hgrow for TextField
HBox.setHgrow(textField, Priority.ALWAYS);
BorderPane pane = new BorderPane();
pane.setCenter(container);
Scene scene = new Scene(pane, 150, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Output :

JavaFX How to 'hide' TitledPane back after expanding

I have TitledPane, which i want to hide back (after expanding - un-expand it) after pressing a button. Is there any way to do it? I didn't find any way :( Thanks!
Just do
titledPane.setExpanded(false);
Complete example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TitledPaneExample extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Some content");
Button button = new Button("OK");
VBox content = new VBox(10, label, button);
TitledPane titledPane = new TitledPane("Titled Pane", content);
button.setOnAction(e -> titledPane.setExpanded(false));
VBox root = new VBox(titledPane);
Scene scene = new Scene(root, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Label text position

I have a Label with an image and text
final Label label = new Label(labelText);
label.setTextAlignment(TextAlignment.CENTER);
ImageView livePerformIcon = new ImageView(MainApp.class.getResource("/images/Folder-icon.png").toExternalForm());
label.setGraphic(livePerformIcon);
I get this as a visual result:
How I can change the text position? I want to set the text below the Image?
label.setContentDisplay(ContentDisplay.TOP);
Play with this to see the effect of the different alignment settings:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
public class LabelGraphicAlignmentTest extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Label label = new Label("Some\ntext");
label.setGraphic(new ImageView(getClass().getResource("/images/Folder-icon.png").toExternalForm()));
label.setMaxWidth(Double.POSITIVE_INFINITY);
label.setMaxHeight(Double.POSITIVE_INFINITY);
label.setStyle("-fx-border-color: blue;");
root.setCenter(label);
ComboBox<ContentDisplay> contentDisplayBox = new ComboBox<>();
contentDisplayBox.getItems().addAll(ContentDisplay.values());
contentDisplayBox.getSelectionModel().select(ContentDisplay.LEFT);
label.contentDisplayProperty().bind(contentDisplayBox.valueProperty());
ComboBox<Pos> alignmentBox = new ComboBox<>();
alignmentBox.getItems().addAll(Pos.values());
alignmentBox.getSelectionModel().select(Pos.CENTER);
label.alignmentProperty().bind(alignmentBox.valueProperty());
ComboBox<TextAlignment> textAlignmentBox = new ComboBox<>();
textAlignmentBox.getItems().addAll(TextAlignment.values());
textAlignmentBox.getSelectionModel().select(TextAlignment.LEFT);
label.textAlignmentProperty().bind(textAlignmentBox.valueProperty());
GridPane ctrls = new GridPane();
ctrls.setHgap(5);
ctrls.setVgap(5);
ctrls.setPadding(new Insets(10));
ctrls.addRow(0, new Label("Content display:"), new Label("Alignment:"), new Label("Text Alignment:"));
ctrls.addRow(1, contentDisplayBox, alignmentBox, textAlignmentBox);
root.setTop(ctrls);
Scene scene = new Scene(root, 600, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I had to center the text of a label which acted like a title. The following code snippet did the trick.
final Label title = new Label("Some text");
title.setMaxWidth(Double.MAX_VALUE);
title.setAlignment(Pos.CENTER);
Good programming :-)
I was able to grab the button from the fxml file:
#FXML Label countDownClockLabel;
Then when the controller was initialized i set the text position:
#FXML
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
countDownClockLabel.setAlignment(Pos.CENTER);
}
You have to import:
import javafx.geometry.Pos;

Resources