how to fix javafx - tableview size to current window size - javafx

I'm totally new to standalone applications. Please any one help me on this.
I have TableView with 6 columns which is half showing in the window as shown below.
I want to fix its current window size, even when the window is expanded, the tableview should auto resize. Is there any way to do this?
This Is The Code Snippet
GridPane tableGrid= new GridPane();
tableGrid.setVgap(10);
tableGrid.setHgap(10);
Label schoolnameL= new Label(SCHOOL+school_id);
schoolnameL.setId("schoolLabel");
Button exportDataSheetBtn= new Button("Export In File");
tableView.setMaxWidth(Region.USE_PREF_SIZE);
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
tableGrid.getChildren().addAll(schoolnameL,exportDataSheetBtn,tableView);

This can be done by binding the preferred height and width to the height and width of the primary stage. Here's an MCVE:
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class MCVE extends Application {
#Override
public void start(Stage stage) {
TableView<ObservableList<String>> table = new TableView<ObservableList<String>>();
// We bind the prefHeight- and prefWidthProperty to the height and width of the stage.
table.prefHeightProperty().bind(stage.heightProperty());
table.prefWidthProperty().bind(stage.widthProperty());
stage.setScene(new Scene(table, 400, 400));
stage.show();
}
public static void main(String[] args) {
launch();
}
}

Create Tabel inside GridPane and Use GridePane inside AnchorPane.Click on GridPane(capture1).
Click on Ancho Pane Constraint inside the GridPane Layout (captur2).
In table view Layout select Hgrow and Vgrow as 'Always'(capture3)

VBox.setVgrow(tableView, Priority.ALWAYS);
OR for your parent layouts:
VBox.setVgrow({{PARENT}}, Priority.ALWAYS);
It fixed for me:

You could use a ScrollPane as the root of the scene and put everything else inside it. Then set the property setFitToWidth and setFitToHeight to true and all the content inside the ScrollPane will be stretched to fit the ScrollPane size and the ScrollPane will fit the Scene since its a Layout Pane. It will also show ScrollBars if the user resizes the window to be smaller than the contents minWidth, so the content doesnt get cut off!
#Override
public void start(Stage stage) {
TableView<ObservableList<String>> table = new TableView<ObservableList<String>>();
table.setMinWidth(400);
ScrollPane sp = new ScrollPane(table);
sp.setFitToHeight(true);
sp.setFitToWidth(true);
stage.setScene(new Scene(table, 800, 600));
stage.show();
}
public static void main(String[] args) {
launch();
}
I copied parts of the MCVE From Jonathan's answer, hope you dont mind Jonathan :)
For more general tips for making resizable GUIs check this post!

Related

How do I fit a JavaFX Pane to the size of its contents?

In JavaFX, I see lots of examples of how to make a child component extend its size to fit the parent pane. But I can't see how to shrink the parent pane to fit the size of its child contents.
In the following example, I create a Stage with a Scene of size 500x500 pixels. Inside that Scene is a VBox that has one child, a single Label.
I'd like the VBox Pane to be the size of the Label, not the size of the whole Stage. (In a more complex application, I'm making the VBox a draggable Pane, so I want it to be just big enough to fit its contents).
How can I do that?
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Sample extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
VBox vbox = new VBox();
vbox.setStyle("-fx-background-color: #efecc2");
vbox.setPrefSize(100, 100);
Label label = new Label("Label");
label.setStyle("-fx-background-color: lightcyan");
vbox.getChildren().add(label);
Scene scene = new Scene(vbox, 500, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
}
As you can see in the picture below, the label (with a blue background) is small, but the VBox (with a yellow background) fills the whole window. It doesn't seem to matter that I set the preferred size of the VBox to 100,100: it still fills up the whole 500 x 300 pixel Scene.
How can I tell the VBox to be only as big as the Label that is inside of it? (Or, when I add, say, 3 things inside it, to be as big as those?)
First problem here is a scene's root object. It will always be the same size as the scene. So you need to add the parent Pane as root element and then add VBox into it.
Second problem is a type of Pane. Some elements affect the size of children(BorderPane, StackPane), some not (Pane, AnchorPane). So you need to choose the right parent.
Here is a simple example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Sample extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Label");
label.setStyle("-fx-background-color: lightcyan");
VBox vBox = new VBox();
vBox.setStyle("-fx-background-color: #efecc2");
vBox.getChildren().add(label);
AnchorPane root = new AnchorPane();
root.getChildren().add(vBox);
Scene scene = new Scene(root, 500, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX TabPane width and Button width donĀ“t match

While I was trying to use the TabPane container in JavaFX I noticed, that if I give the Tabs in the TabPane a specific width and another element e.g. a Button the exact same width, they show up on the screen with different sizes.
Here is an example: As you can see in this image, the Button is smaller than the width of the tap
Here is the Code I for this specific image:
package stackOverflow;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class TabPaneMystery extends Application {
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
StackPane stackPane = new StackPane();
Scene scene = new Scene(stackPane, 600, 400);
stage.setScene(scene);
stage.show();
TabPane tabPane = new TabPane();
stackPane.getChildren().add(tabPane);
Tab tab1 = new Tab();
tabPane.setTabMaxWidth(160); //The width of the tab is '160'
tabPane.setTabMinWidth(160);
tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
tab1.setText("Tab");
tabPane.getTabs().add(tab1);
Button b = new Button();
b.setText("Button");
b.setPrefWidth(160); //The width of the button is '160'
b.setTranslateX(6);
tab1.setContent(b);
}
}
in Line 33 and 34 (where the first comment is) I set the width of the tapPane to be 160 and in Line 42 (where the second comment is) I set the exact same width
This results in the shown image.
My question is:
Have I made an obvious mistake or is it some kind of bug or does the compiler interpret the width for every node somewhat different?
I suspect you're seeing some padding in the Tab. The actual width of the Tab comes out to 170. You can confirm this by changing the width of the Tab to 150; it will then be the exact same size as the Button:
You could also use CSS to remove the padding:
tab1.setStyle("-fx-padding: 0");
Although, as you can see below, it isn't an exact match and there may be other CSS properties to look into. Hope this gets you closer to your goal, though:

JavaFX: Determine Bounds of a node while being invisible?

is there any way to determine the bounds (especially height and width) of a node which is already attached to a scene but set to invisible?
I want to show a label on screen only if its width exceeds 100px... but it is always 0:
#Override
public void start(Stage primaryStage) {
Group root = new Group();
Scene scene = new Scene(root, 500, 500, Color.BLACK);
primaryStage.setScene(scene);
primaryStage.show();
Label n = new Label();
n.setVisible(false);
n.setStyle("-fx-background-color: red;");
root.getChildren()
.addAll(n);
n.textProperty()
.addListener((v, ov, nv) -> {
System.out.println(n.getBoundsInParent());
n.setVisible(n.getWidth() > 100);
});
n.setText("TEST11111111111111111111111");
}
The result of the sysout: (also n.getWidth() is no better)
BoundingBox [minX:0.0, minY:0.0, minZ:0.0, width:0.0, height:0.0, depth:0.0, maxX:0.0, maxY:0.0, maxZ:0.0]
Is there any trick ?
Thanks all!
Your problem is that you are listening for changes to the text property and expecting the width of the node to be updated at that time - but it's not. The width of nodes are only calculated and set during a render pass which consists of an applyCSS and layout routine (see: Get the height of a node in JavaFX (generate a layout pass)). Your code incorrectly sets the node to invisible before the updated size of the node is calculated.
Instead of using a listener on the text property to determine visibility of the node, I suggest that you use a binding expression to create a direct binding on the visibility property to the desired width property. An example of this approach is provided below. You can see that the label only displays when the text to display is longer than the required width (in this case 100 pixels).
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class BoundSample extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Pane root = new Pane();
Scene scene = new Scene(root, 200, 100);
primaryStage.setScene(scene);
primaryStage.show();
Label n = new Label();
n.setVisible(false);
n.visibleProperty().bind(n.widthProperty().greaterThan(100));
TextField textField = new TextField("TEST11111111111111111111111");
n.textProperty().bind(textField.textProperty());
textField.relocate(0, 50);
root.getChildren().addAll(n, textField);
}
}

JavaFX Fill empty space when component is not visible?

i use Linux Suse 12.3, JDK 1.7.0-45, JavaFX 2.2.
my Question is: why the following Code not working and how to implement a toggleShow/hide functionality?
here is my Test Code:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage;
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage stage) {
AnchorPane root = new AnchorPane();
BorderPane inner = new BorderPane();
AnchorPane.setTopAnchor(inner, 0.0);
AnchorPane.setRightAnchor(inner, 0.0);
AnchorPane.setBottomAnchor(inner, 0.0);
AnchorPane.setLeftAnchor(inner, 0.0);
final HTMLEditor center = new HTMLEditor();
final ToolBar top = new ToolBar();
final Button button = new Button("hide");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
top.setVisible(false);
//center.setPrefSize(Double.MAX_VALUE, Double.MAX_VALUE);
}
});
center.setManaged(false);
top.getItems().add(button);
//top.managedProperty().bind(top.visibleProperty());
top.setManaged(false);
inner.setTop(top);
inner.setCenter(center);
root.getChildren().add(inner);
Scene scene = new Scene(root,600,400);
stage.setScene(scene);
stage.show();
}
}
what i want is the same effect as the Solution of Sergey to this Question but without changing width/height!:
How to solve the overlapping of the controls each other belonging to two different panes
as i said its just a Test Code. i tried using another Layouts as BorderPane but still not working. i don't want to recalculate the size's manually ...etc. Removing the node and adding it again is not an option for me.
whats wrong in my Code? any idea is welcomed!
thanks
Filling the empty space with the usage of BorderPane seems to be not an option, due to the prompt in its javadoc:
BorderPane lays out each child set in the five positions regardless of
the child's visible property value; unmanaged children are ignored.
Additionally, using AnchorPane just for resizable content as:
AnchorPane.setTopAnchor(inner, 0.0);
AnchorPane.setRightAnchor(inner, 0.0);
AnchorPane.setBottomAnchor(inner, 0.0);
AnchorPane.setLeftAnchor(inner, 0.0);
seems to be an overusing. Just using the VBox will be more suitable for your layout case.
Rewritten test code:
#Override
public void start(final Stage stage) {
final HTMLEditor center = new HTMLEditor();
final ToolBar top = new ToolBar();
final Button button = new Button("hide");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
top.setVisible(false);
top.setManaged(false);
}
});
top.getItems().add(button);
VBox inner = new VBox();
inner.getChildren().addAll(top, center);
Scene scene = new Scene(inner, 600, 400);
stage.setScene(scene);
stage.show();
}
Now the question is;
How are you going to implement the "show" part of your "show/hide" toggle bar? Since there is no clue about it in your question.
Try to remove the top.setManaged(false); line and then put the toolbar into a Group object like this:
Group g = new Group();
Region spacer = new Region();
spacer.setPrefWidth(10000);
spacer.setMinWidth(100);
top.getItems().add(spacer);
g.getChildren().add(top); //Toolbar here...
inner.setTop(g); //set Group into Borderpane instead of the toolbar
After clicking the button the free space is consumed entirely by the HTML-Editor.

View of the application javafx

i was searching in google for hours and i still cant find the right answer, so i have a last chance to come here and ask.
i'm making school year JAVA FX project. I'm using NetBeans.
I have a point that i can see on the application i have. The problem is: I would like to have a big map (background) and I need to be able to move with my view. For example move by 50 to the right (x).
I have Application where I use Stage, Scene, StackPane.
I heard something about Dimensions in Java, but i can't use it in javafx application. Is there something similar, what can I use in my Application?
Thank you very much.
What I think you are asking for is a Scene with a map (represented as an Image) in the background and controls layered on top of the map to allow interaction with the map at certain positions. Your question is a little unclear, so I'm not exactly sure if that is what you are asking.
If so, here is some sample code to implement that.
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
/** Constructs a scene with a pannable Map background. */
public class PannableView extends Application {
private Image backgroundImage;
#Override public void init() {
backgroundImage = new Image("https://www.narniaweb.com/wp-content/uploads/2009/08/NarniaMap.jpg");
}
#Override public void start(Stage stage) {
stage.setTitle("Drag the mouse to pan the map");
// construct the scene contents over a stacked background.
StackPane layout = new StackPane();
layout.getChildren().setAll(
new ImageView(backgroundImage),
createKillButton()
);
// wrap the scene contents in a pannable scroll pane.
ScrollPane scroll = createScrollPane(layout);
// show the scene.
Scene scene = new Scene(scroll);
stage.setScene(scene);
stage.show();
// bind the preferred size of the scroll area to the size of the scene.
scroll.prefWidthProperty().bind(scene.widthProperty());
scroll.prefHeightProperty().bind(scene.widthProperty());
// center the scroll contents.
scroll.setHvalue(scroll.getHmin() + (scroll.getHmax() - scroll.getHmin()) / 2);
scroll.setVvalue(scroll.getVmin() + (scroll.getVmax() - scroll.getVmin()) / 2);
}
/** #return a control to place on the scene. */
private Button createKillButton() {
final Button killButton = new Button("Kill the evil witch");
killButton.setStyle("-fx-base: firebrick;");
killButton.setTranslateX(65);
killButton.setTranslateY(-130);
killButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent t) {
killButton.setStyle("-fx-base: forestgreen;");
killButton.setText("Ding-Dong! The Witch is Dead");
}
});
return killButton;
}
/** #return a ScrollPane which scrolls the layout. */
private ScrollPane createScrollPane(Pane layout) {
ScrollPane scroll = new ScrollPane();
scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setPannable(true);
scroll.setPrefSize(800, 600);
scroll.setContent(layout);
return scroll;
}
public static void main(String[] args) { launch(args); }
}
For the example use the mouse (or probably touch commands or trackpad scroll gestures - though I haven't a touch screen or trackpad to test it) to drag the map around. Click on the button to "Kill the evil witch".
The solution works by:
Creating an ImageView to hold the background map.
Constructing the scene contents in a StackPane over the stacked background ImageView.
Wrapping the scene in a ScrollPane bound to the scene's size.
Setting properties on the ScrollPane to make it pannable.

Resources