Javafx make combobox expand upward - javafx

I have a window which has a combobox at the bottom. When I click on it, not all the options are visible because they are not inside the screen area anymore. How can I make the drop-down list display upwards instead of downards?
I have the ComboBox defined in SceneBuilder. I define it in my code this way:
#FXML
ComboBox fontsComboBox;
In my initialize() method of the controller assigned to that window I have set some properties:
fontComboBox.setVisibleRowCount(3);
fontComboBox.getItems().addAll(fontList);
fontComboBox.setValue(fontList[0]);
I'm pretty sure I need to add something here in order to make the dropdown list fo up.
Thanks,
Serban

This was a known bug till Java 8u45. It is fixed in Java 8u60.
https://bugs.openjdk.java.net/browse/JDK-8092942 (fixed in 8u60)
You can download JDK/JRE 8u60ea (early access) here to give it a try: https://jdk8.java.net/download.html
Java 8 Update 60 is scheduled GA for August 2015.
This example shows the problem. Simply open the combobox, even if you move the window down to screen, it won't show the list above the box.
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ComboBoxTester extends Application {
#Override
public void start(Stage primaryStage) {
List<Integer> values = new ArrayList<>();
for (int i = 1; i < 100; i++) {
values.add(i);
}
ObservableList<Integer> items = FXCollections.observableArrayList(values);
ComboBox<Integer> comboBox = new ComboBox<>(items);
comboBox.getSelectionModel().clearAndSelect(0);
comboBox.setVisibleRowCount(5);
BorderPane root = new BorderPane();
root.setBottom(comboBox);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Java 8 Update 45 behaviour
Java 8 Update 60 ea behaviour

Related

How to use modal dialog in this case?

I have a question. I need to make a GridPane with a directory choose that will then lead me to a modal dialog showing photos. I cannot figure how to do the modal dialog that also has to be a GridPane or a HBox...so the question is , how do I get to show a Modal Dialog after selecting the Folder and pressing the "Show" Button... Thanks a lot!
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
public class FotoView extends Application {
#Override
public void start(Stage primaryStage) {
TextField tf = new TextField();
Button b1 = new Button("Search");
Button b2 = new Button("Show");
DirectoryChooser dc = new DirectoryChooser();
GridPane gp = new GridPane();
gp.add(tf, 0 , 0);
gp.add(b1, 1, 0);
gp.add(b2, 0, 1);
b1.setOnAction(e-> dc.showDialog(primaryStage));
primaryStage.setScene(new Scene(gp)) ;
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
} ```
Below is a quick example where a first window has a button that opens up a DirectoryChooser. Once a directory has been selected a second smaller window opens up with the Modality set to APPLICATION_MODAL. In this second window you could add the image(s) that you load and add them to the GridPane.
import java.io.File;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(final String[] args) {
launch(args);
}
#Override
public void start(final Stage aStage) throws Exception {
final HBox root = new HBox();
final Button browseBtn = new Button("Click to open a Directory chooser");
root.getChildren().add(browseBtn);
browseBtn.setOnAction(e -> {
final DirectoryChooser chooser = new DirectoryChooser();
final File dir = chooser.showDialog(aStage);
openNewModalStage(aStage, dir);
});
final Scene scene = new Scene(root, 500, 500);
aStage.setScene(scene);
aStage.show();
}
private void openNewModalStage(final Stage aStage, final File aDirectory) {
final Stage stage = new Stage();
final GridPane grid = new GridPane();
final Scene scene = new Scene(grid);
grid.setStyle("-fx-background-color:black");
grid.setPrefWidth(400);
grid.setPrefHeight(400);
// get your images from 'aDirectory' and add them to your grid pane.
stage.setScene(scene);
// set the new windows Modality.
stage.initModality(Modality.APPLICATION_MODAL);
stage.show();
}
}
This way you would only need the one button and the dialog would show as soon as you've selected a directory. However, if you would still want a Search and Show button then just store the directory as a variable and add a listener on the 'show' button and move the openNewModalStage call to that one and remove the second argument.
Edit:
Also, depending on how many images and exactly what you want to display in the modal window, you might want to reconsider the GridPane and use a TilePane, or an hbox/vbox inside of a scroll pane. It's just a thought but I don't know what you will be doing with the GridPane.

JavaFX Slider : How to drag the thumb only by increments

I am trying to implement the Slider such that user can drag only by given increments. I tried in different ways by using the Slider API, but didnt get the desired results. Below is a quick demo of what I had tried. I am expecting to drag the thumb only in increments of 10 not with intermediate values. snapToTicks is doing what I required, but only after finishing the drag. I am trying to not move the thumb till the next desired block increment is reached.
Can anyone let me know how can i achieve this. Below is the screenshot while dragging.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SliderDemo extends Application {
public static void main(String... args){
Application.launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Label label = new Label();
label.setStyle("-fx-font-size:30px");
Slider slider = new Slider(5,240,5);
slider.setBlockIncrement(10);
slider.setMajorTickUnit(10);
slider.setMinorTickCount(0);
slider.setShowTickLabels(true);
slider.setShowTickMarks(true);
slider.setSnapToTicks(true);
slider.valueProperty().addListener((obs,old,val)->label.setText((int)Math.round(val.doubleValue())+""));
VBox root = new VBox(slider,label);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(20));
root.setSpacing(20);
Scene scene = new Scene(root,600,200);
stage.setScene(scene);
stage.show();
}
}
The solution is to set the value of the slider directly inside of the listener. The listener will not be called again
final ChangeListener<Number> numberChangeListener = (obs, old, val) -> {
final double roundedValue = Math.floor(val.doubleValue() / 10.0) * 10.0;
slider.valueProperty().set(roundedValue);
label.setText(Double.toString(roundedValue));
};
slider.valueProperty().addListener(numberChangeListener);
If you use Math.floor() instead of round you get a more intuatuive behavior of the thumb.

Wizard with JavaFX Accordions

I'm writing a small configuration-wizard-style JavaFX application. I want to force the user through different steps of configuration panes. So I've chosen an accordion container with a few panels. The user is only allowed to proceed to the NEXT or PREVIOUS accordion panel, but may not jump from panel 1 to 3.
I achived this by adding the "Previous" and "Next" button under the accordion and I set the mouse transparency of the accordion to true. Everything works fine so far. The user can walk from panel 1 to 5 and back...
Unfortunately (for any strange reason) the user cannot configure nothing inside the different panels. Wait... I set the mouse transparency to "true", right... But when I set it to false, the user can jump through the panels without any order.
Any suggestions?
One possible way is to set the collapsible property of all the panes to false, and to set each one to true just when it needs to be expanded or collapsed (which you can do programmatically). This is a little ugly, but here's an example:
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class AccordionBasedWizard extends Application {
#Override
public void start(Stage primaryStage) {
Accordion accordion = new Accordion();
for (int i = 0 ; i < 5 ; i++) {
TitledPane pane = new TitledPane("Page "+(i+1), new Label("Wizard page "+(i+1)));
accordion.getPanes().add(pane);
pane.setCollapsible(false);
}
accordion.setExpandedPane(accordion.getPanes().get(0));
Button previousButton = new Button("Previous");
previousButton.disableProperty().bind(accordion.expandedPaneProperty().isEqualTo(accordion.getPanes().get(0)));
previousButton.setOnAction(e -> {
TitledPane current = accordion.getExpandedPane();
int index = accordion.getPanes().indexOf(current);
TitledPane previous = accordion.getPanes().get(index - 1);
current.setCollapsible(true);
previous.setCollapsible(true);
accordion.setExpandedPane(previous);
previous.setCollapsible(false);
current.setCollapsible(false);
});
Button nextButton = new Button("Next");
nextButton.disableProperty().bind(accordion.expandedPaneProperty().isEqualTo(accordion.getPanes().get(accordion.getPanes().size()-1)));
nextButton.setOnAction(e -> {
TitledPane current = accordion.getExpandedPane();
int index = accordion.getPanes().indexOf(current);
TitledPane next = accordion.getPanes().get(index + 1);
current.setCollapsible(true);
next.setCollapsible(true);
accordion.setExpandedPane(next);
next.setCollapsible(false);
current.setCollapsible(false);
});
HBox buttons = new HBox(5, previousButton, nextButton);
buttons.setAlignment(Pos.CENTER);
buttons.setPadding(new Insets(5));
BorderPane root = new BorderPane(accordion);
root.setBottom(buttons);
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
For what it's worth, I probably wouldn't try to use an Accordion as a wizard, and would just use a BorderPane, with the current "wizard page" in the center and next and previous buttons in the bottom. You can add a breadcrumb trail too if you need.

Set Graphic to label

I want to set Label to graphic. I tested this code:
private static final ImageView livePerformIcon;
static
{
livePerformIcon = new ImageView(MainApp.class.getResource("/images/Flex.jpg").toExternalForm());
}
final Label label = new Label();
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
livePerformIcon.setFitHeight(20);
livePerformIcon.setFitWidth(20);
label.setGraphic(livePerformIcon);
But I don't see any image.
The only way that I found to make it work is this:
label.setStyle("-fx-background-image: url(\"/images/Flex.jpg\");");
Is there a way to solve this?
Not sure, but AFAIK controls should be created on the JavaFX Application thread, but you're creating ImageView in a static initializer, which I'm not sure if it's executed on the Application thread.
Besides: Do you really want livePerformIcon to be static???
This one made from the data used in the docs, works perfectly for me
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class LabelWithImages extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Label With Image Sample");
stage.setWidth(400);
stage.setHeight(180);
HBox hbox = new HBox();
//Replace the image you want to put up
Image image = new Image(getClass().getResourceAsStream("a.png"));
Label label = new Label("Demo Label");
label.setGraphic(new ImageView(image));
hbox.setSpacing(10);
hbox.getChildren().add((label));
((Group) scene.getRoot()).getChildren().add(hbox);
stage.setScene(scene);
stage.show();
}
}
Code snippets below will set the value of the property graphic of a label. You can use any of the two. I prefer using javafx css, just to implement the model-view-controller design.
// programmatically, provided with image input stream
label.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("path/to/image.png"))));
// javafx css, provided with image url
.label {
-fx-graphic: url("path/to/image.png");
}

JavaFX: SplitPane Mouse Handling Breaks After Displaying an Application-Modal Stage

Mouse handling on the SplitPane and ScrollBar controls breaks after displaying an application-modal Stage. The problem goes away after the application window loses and regains focus. Does anyone know a solution or workaround to this problem?
In what way is the mouse handling broken? When you click and start dragging on the control (SplitPane or ScrollBar), the control stops responding to your mouse movements the moment your mouse cursor leaves the control by a single pixel. This requires the user to be impossibly precise with the mouse. You would expect the control to respond to mouse movements, no matter where your mouse cursor happens to be, up until you release the mouse button.
The following code exhibits the problem on Ubuntu Linux and JRE 1.7.0_21. I have seen the problem on other JREs, but I have not tried another OS.
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.Modality;
public class SplitPaneBug extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button button = new Button(
"Move the SplitPane divider, then click here to show the modal"
+ " dialog.");
button.setOnAction(
new EventHandler() {
public void handle(Event event) {
Stage dialog = new ModalDialog();
dialog.showAndWait();
}
});
button.setMaxWidth(Double.MAX_VALUE);
SplitPane splitPane = new SplitPane();
splitPane.getItems().setAll(new BorderPane(), new BorderPane());
VBox vbox = new VBox();
vbox.getChildren().setAll(button, splitPane);
vbox.setVgrow(splitPane, Priority.ALWAYS);
primaryStage.setTitle("SplitPane Bug?");
primaryStage.setScene(new Scene(vbox, 640, 480));
primaryStage.show();
}
class ModalDialog extends Stage {
public ModalDialog() {
Button button = new Button(
"Click here to dismiss this dialog, then move the SplitPane"
+ " divider again.");
button.setOnAction(
new EventHandler() {
public void handle(Event event) {
close();
}
});
BorderPane borderPane = new BorderPane();
borderPane.setCenter(button);
initModality(Modality.APPLICATION_MODAL);
setTitle("Modal Dialog");
setScene(new Scene(borderPane, 600, 100));
sizeToScene();
}
}
}
Are you sure that you use 7u21? Please, set to output VersionInfo.getRuntimeVersion().
I don't reproduce on my ubuntu 12.10 with jdk 7u21(b11) downloaded from official site,
but there is known bug in fx 8.0 - https://javafx-jira.kenai.com/browse/RT-29576

Resources