When I change scenes on my stage with the following code, my stage changes size. However the button in the top right to maximize/minimize the windows says that the stage is still maximized even though it is clearly not.
How am I able to keep the stage maximized when a scene change happens?
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class Program2 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
try {
StackPane p = new StackPane();
primaryStage.setTitle("Chart Application");
Label loader = new Label("Loading...");
loader.setGraphic(new ImageView(new Image("https://media.giphy.com/media/FmcNeI0PnsAKs/giphy.gif")));
loader.setFont(new Font(35));
p.setStyle("-fx-background: #FFFFFF;");
p.getChildren().add(loader);
StackPane.setAlignment(loader, Pos.CENTER);
primaryStage.setScene(new Scene(p));
primaryStage.setMaximized(true);
Task<VBox> task = new Task<VBox>() {
#Override
public VBox call() {
VBox result = new VBox();
for(int i = 0; i < 50000; i++) { //Here simply for small delay
result.getChildren().add(new Label(Integer.toString(i)));
}
return result ;
}
};
task.setOnSucceeded(e -> {
VBox result = task.getValue();
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(result);
scrollPane.setStyle("-fx-background: #FFFFFF;");
primaryStage.setScene(new Scene(scrollPane));
});
new Thread(task).start();
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
As this is operating system specific I image I am using Windows 10 with JDK 8 u112 and JavaFX 8 with the e(fx)clipse plugin for eclipse
Instead of replacing the scene, use the same scene and replace its root:
primaryStage.getScene().setRoot(scrollPane);
Related
I found a little bug in JavaFX TabPane, and am looking for a workaround. I am running JavaFX 13.0.1.
How it happens:
The TabPane's DragPolicy must be set to TabPane.TabDragPolicy.REORDER.
You can navigate between tabs via keyboard shortcuts CTRL + TAB & CTRL + SHIFT + TAB.
However, if I drag, say, the last tab to the very left and release it back to the position it was in (so that nothing should change), these keyboard shortcuts get messed up - no longer pointing to proper next/previous tabs.
You should be able to reproduce it simply with the following code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test extends Application {
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setTabDragPolicy(TabPane.TabDragPolicy.REORDER);
tabPane.getTabs().add(new Tab("First"));
tabPane.getTabs().add(new Tab("Second"));
tabPane.getTabs().add(new Tab("Third"));
tabPane.getTabs().add(new Tab("Fourth"));
tabPane.getTabs().add(new Tab("Fifth"));
StackPane root = new StackPane();
root.getChildren().add(tabPane);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("TabPane bug");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
An interesting bug. It appears TabPane.getTabs() returns a List which may or may not reflect the visual ordering of the tabs. But the navigation keys always rely on the getTabs() order, not the visual order.
One workaround is to use a Label as a graphic for each Tab, while leaving the Tab’s text as null. You can then keep the Tabs sorted properly yourself, by checking the visual position of each such Label.
import java.util.List;
import java.util.ArrayList;
import javafx.beans.Observable;
import javafx.geometry.Bounds;
import javafx.geometry.NodeOrientation;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class TabDragTest2 extends Application {
private static Tab createTab(String title) {
Tab tab = new Tab();
tab.setGraphic(new Label(title));
return tab;
}
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setTabDragPolicy(TabPane.TabDragPolicy.REORDER);
tabPane.getTabs().add(createTab("First"));
tabPane.getTabs().add(createTab("Second"));
tabPane.getTabs().add(createTab("Third"));
tabPane.getTabs().add(createTab("Fourth"));
tabPane.getTabs().add(createTab("Fifth"));
tabPane.getTabs().addListener((Observable o) -> {
List<Tab> tabs = new ArrayList<>(tabPane.getTabs());
NodeOrientation orientation = tabPane.getEffectiveNodeOrientation();
boolean ltr = orientation == NodeOrientation.LEFT_TO_RIGHT;
tabs.sort((t1, t2) -> {
Node title1 = t1.getGraphic();
Node title2 = t2.getGraphic();
Bounds title1Bounds =
title1.localToScene(title1.getLayoutBounds());
Bounds title2Bounds =
title2.localToScene(title2.getLayoutBounds());
if (tabPane.getSide().isHorizontal()) {
if (ltr) {
return Double.compare(
title1Bounds.getMinX(), title2Bounds.getMinX());
} else {
return Double.compare(
title2Bounds.getMaxX(), title1Bounds.getMaxX());
}
} else {
return Double.compare(
title1Bounds.getMinY(), title2Bounds.getMinY());
}
});
if (!tabPane.getTabs().equals(tabs)) {
Platform.runLater(() -> tabPane.getTabs().setAll(tabs));
}
});
StackPane root = new StackPane();
root.getChildren().add(tabPane);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("TabPane bug");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I'm creating an app with javafx and I want to separate ui files.
Like: Tabs in separate file and just import and create new Tab in main app.
I have tried it, but when I try to set it on main app like borderPane.setCenter(tabPane); it says that The method setCenter(Node) in the type BorderPane is not applicable for the arguments (Tabs)
Main.java app code
import javafx.application.Application;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.*;
import javafx.stage.Stage;
import utils.Tabs;
public class Main extends Application {
#Override
public void start(Stage window) throws Exception {
Group root = new Group();
Scene scene = new Scene(root, 400, 250, Color.WHITE);
BorderPane borderPane = new BorderPane();
Tabs tabs = new Tabs();
// bind to take available space
borderPane.prefHeightProperty().bind(scene.heightProperty());
borderPane.prefWidthProperty().bind(scene.widthProperty());
borderPane.setCenter(tabs);
root.getChildren().add(borderPane);
window.setTitle("Computer Security — Demos");
window.setScene(scene);
window.show();
}
public static void main(String[] args) {
launch(args);
}
}
Tabs.java
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.HBox;
public class Tabs extends TabPane {
public Tabs() {
TabPane tabPane = new TabPane();
Tab tab = new Tab("Tab: ");
HBox hbox = new HBox();
hbox.getChildren().add(new Label("Tab"));
hbox.setAlignment(Pos.CENTER);
tab.setContent(hbox);
tabPane.getTabs().add(tab);
}
}
I made a javafx program using a horizontal SplitPane with a Canvas on one side in which something is drawn. When the SplitPane is resized the Canvas resizes with it.
Everything worked fine until I switched to Java 10. Suddenly the Canvas-side can only be expanded, not reduced.
Anyone has an idea why that is?
(The working Java version was 1.8.0_181)
package test;
import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test extends Application {
private static Display display;
#Override
public void start(Stage primaryStage) {
display = new Display();
StackPane stackPaneDisplay = new StackPane();
stackPaneDisplay.getChildren().add(display);
stackPaneDisplay.setStyle("-fx-background-color: white");
AnchorPane anchorPaneDisplay = new AnchorPane();
anchorPaneDisplay.getChildren().add(stackPaneDisplay);
AnchorPane.setBottomAnchor(stackPaneDisplay, Double.MIN_VALUE);
AnchorPane.setTopAnchor(stackPaneDisplay, Double.MIN_VALUE);
AnchorPane.setLeftAnchor(stackPaneDisplay, Double.MIN_VALUE);
AnchorPane.setRightAnchor(stackPaneDisplay, Double.MIN_VALUE);
display.widthProperty().bind(stackPaneDisplay.widthProperty());
display.heightProperty().bind(stackPaneDisplay.heightProperty());
StackPane stackPaneLeft = new StackPane();
SplitPane splitPane = new SplitPane();
splitPane.setOrientation(Orientation.HORIZONTAL);
splitPane.getItems().addAll(stackPaneLeft, anchorPaneDisplay);
BorderPane root = new BorderPane();
root.setCenter(splitPane);
Scene scene = new Scene(root);
primaryStage.setMaximized(true);
primaryStage.setScene(scene);
primaryStage.show();
splitPane.setDividerPositions(0.2);
}
public static void main(String[] args) {
launch(args);
}
}
and the Canvas-Class
package test;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
public class Display extends Canvas {
GraphicsContext gc = this.getGraphicsContext2D();
public Display() {
widthProperty().addListener(e -> {
draw();
});
}
public void draw() {
gc.strokeOval(500, 500, 100, 100);
}
}
Thanks in advance
I have created a simple app to simulate dynamic node creation with JAVAFX.
This app has the ability to create a new window whenever user want it by clicking the "New" button.
User can add a new node which is TitledPane to the window by clicking "Add Task" button and then clicking "Add" button on the dialog window.
There are an unexpected behavior which I want to fix. This app is only add new node (TitledPane in this case) to the last created window.
And the all of the nodes on the previous window will vanish.
You can see the following video to better understand what I mean.
VIDEO
https://youtu.be/eaWmu3zuuhE
NETBEANS PROJECT
Just in case you want to play with it.
https://drive.google.com/file/d/0B4Sbb8Ym-lcZLUIyWHV5ZXRSZE0/view?usp=sharing
CODES:
TasksList.java
package taskslist;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.stage.Stage;
public class TasksList extends Application {
DisplayWhich display = new DisplayWhich();
Stage primaryStage;
Parent startWindow;
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
initStart();
}
private void initStart(){
display.showDialogWindow();
}
public static void main(String[] args) {
launch(args);
}
}
TheList.java
package taskslist.view;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import taskslist.DisplayWhich;
public class TheList extends BorderPane {
public static VBox listWrapper;
public static ScrollPane listScroller;
public ObservableList<TitledPane> tasks;
private List<String> titles = new ArrayList<>();
public TheList(){
tasks = FXCollections.observableArrayList();
listWrapper = new VBox(5);
listScroller = new ScrollPane(listWrapper);
}
public void setTitles(String... title){
titles = Arrays.asList(title);
}
public List<String> getTitles(){
return titles;
}
public void loadSavedList(){
for(int i=0; i<getTitles().size();i++){
String ttlString = getTitles().get(i);
this.createTask(ttlString);
}
// Display Tasks
listWrapper.getChildren().addAll(this.tasks);
}
// Dialong for adding a new task and also editing a task
private void addTaskDialog(){
GridPane container = new GridPane();
Scene scene = new Scene(container, 150, 50);
Stage addNewTask = new Stage();
addNewTask.initModality(Modality.APPLICATION_MODAL);
addNewTask.setTitle("Add Task");
TextField title = new TextField();
Button confirm = new Button("Add");
// Create Task
confirm.setOnAction((ev) -> {
String ttlString = title.getText();
this.createTask(ttlString);
listWrapper.getChildren().clear();
listWrapper.getChildren().addAll(this.tasks);
addNewTask.close();
});
container.add(title, 0, 1);
container.add(confirm, 0, 5);
addNewTask.setScene(scene);
addNewTask.showAndWait();
}
// Assemble all this.tasks list components
public void render(){
setCenter(listScroller);
loadSavedList();
Button newProject = new Button("New");
Button addTask = new Button("Add Task");
BorderPane listBottom = new BorderPane();
HBox bottomLeft = new HBox();
bottomLeft.getChildren().add(newProject);
listBottom.setLeft(bottomLeft);
HBox bottomRight = new HBox();
bottomRight.getChildren().add(addTask);
listBottom.setRight(bottomRight);
newProject.setOnAction((evt) -> {
DisplayWhich display = new DisplayWhich();
display.showDialogWindow();
});
addTask.setOnAction((e) -> {
addTaskDialog();
});
setBottom(listBottom);
}
// Cteate task from strings
private void createTask(String... strings){
String taskTitle = strings.length > 0 ? strings[0] : "";
TitledPane task = new TitledPane();
task.setPrefWidth(647);
task.setExpanded(false);
task.setText(taskTitle);
this.tasks.add(task);
}
}
NewDialog.java
package taskslist.view;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import taskslist.DisplayWhich;
public class NewDialog {
DisplayWhich display = new DisplayWhich();
Stage stage = new Stage();
Parent startWindow = new AnchorPane();
#FXML
private Button cancelNew;
#FXML
private Button confirmCreation;
/**
* Initializes the controller class.
*/
#FXML
private void initialize() {
}
#FXML
private void cancelNewCreation(ActionEvent event) {
((Stage)cancelNew.getScene().getWindow()).close();
}
#FXML
private void confirmCreateNew(ActionEvent event) {
((Stage)confirmCreation.getScene().getWindow()).close();
TheList wrap = new TheList();
TheWindow window = new TheWindow();
window.makeWindow(wrap);
wrap.setTitles("one", "two", "three", "four");
wrap.render();
}
}
DisplayWhich.java
package taskslist;
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import taskslist.view.TheList;
public class DisplayWhich {
Stage stage = new Stage();
Parent startWindow = new AnchorPane();
public DisplayWhich(){}
public Stage showDialogWindow(){
try {
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Create New Project");
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/taskslist/view/newDialog.fxml"));
startWindow = loader.load();
Scene scene = new Scene(startWindow);
stage.setScene(scene);
stage.setOnCloseRequest((event) -> {
System.out.println("test");
});
stage.showAndWait();
} catch (IOException ex) {
ex.printStackTrace();
}
return stage;
}
}
TheWindow.java
package taskslist.view;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TheWindow {
public TheWindow(){}
public void makeWindow(BorderPane group) {
Stage mainWindow = new Stage();
Scene scene = new Scene(group, 650, 550);
mainWindow.setScene(scene);
mainWindow.setTitle("Task List");
mainWindow.centerOnScreen();
mainWindow.show();
}
}
Why that weird behavior happening and how to fix it so it only adds new node to the same window where the clicked "Add Task" button is located?
These fields should not be static:
public static VBox listWrapper;
public static ScrollPane listScroller;
I'm new to javaFX and I wanted to make a simple code that counted how many times a person pressed a button and displayed the count on the application itself. Currently I have my code printing the counter in my IDE and would just like to some how attach it to the scene(eg I click run and every time I click the button it prints how many times I've clicked it in my workbench). I looked around stack overflow and youtube but the closest I got to what I was looking for was printing it in my IDE. Thanks for any help.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class JavaFXTest extends Application {
private int counter = 0;
public static void main (String [] args){
Application.launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
Stage stage = new Stage();
stage = primaryStage;
Pane pane = new Pane();
pane.setPrefSize(400,400);
Button button = new Button("Smash it!");
HBox root = new HBox(5, pane);
button.setOnAction(e -> {
counter();
});
root.getChildren().add(button);
Scene scene1 = new Scene(root,1000, 800, Color.AQUA);
stage.setScene(scene1);
stage.setTitle("ButtonSmash!");
stage.show();
}
public void counter(){
counter++;
System.out.println(counter);
}
}
Here is the full code:
package StackOverFlow;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class JavaFXTest extends Application {
private int counter = 0;
private Label label = new Label("Count: ");
public static void main (String [] args){
Application.launch();
}
#Override
public void start(Stage primaryStage) throws Exception {
Stage stage = new Stage();
stage = primaryStage;
Pane pane = new Pane();
pane.setPrefSize(400,400);
Button button = new Button("Smash it!");
HBox root = new HBox(5, pane);
button.setOnAction(e -> {
label.setText("Count: "+Integer.toString(counter));
counter();
});
root.getChildren().add(button);
label.relocate(0, 0); // You can put this label, wherever you want!
root.getChildren().add(label);
Scene scene1 = new Scene(root,1000, 800, Color.AQUA);
stage.setScene(scene1);
stage.setTitle("ButtonSmash!");
stage.show();
}
public void counter(){
counter++;
//System.out.println(counter);
}
}
You had to make one label and to add it to your pane.getChildren();
And whenever you press the button you need to change text from that label.