I am currently using JavaFx ComboBox and I load the options from a XML file.
The problem I have is that some items are too long and they don't fit well:
I have tried using CSS width:
.combo-box {
-fx-pref-width: 300;
}
.combo-box-popup > .list-view {
-fx-pref-width: 300;
}
Is it possible to display ComboBox items in two lines instead of displaying in one line?
You'll want to setup a custom CellFactory for your ComboBox. Within the new ListCell we build, we can use a simple Label that wraps the text for us.
Here is a complete example to demonstrate:
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.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ComboBoxTextWrap extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
// The ComboBox
ComboBox<String> comboBox = new ComboBox<>();
// Sample data
comboBox.getItems().addAll(
"Shorty",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
"Shorty Jr.",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
);
// Create our custom cells for the ComboBox
comboBox.setCellFactory(param -> new ListCell<String>() {
// Create a Label to store our text. We'll set it to wrap text and it's preferred width
final Label label = new Label() {{
setWrapText(true);
setPrefWidth(200);
}};
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
// Add our text to the Label
label.setText(item);
setGraphic(label);
}
}
});
// Add the combobox to the layout
root.getChildren().add(comboBox);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
}
The Result:
Related
I am making a login GUI and after I enter the username, I want to hit ENTER key and it will select the password text field. How can I achieve this?
My attempt:
#FXML
void userNameKeyPressed(KeyEvent event) {
if(event.getCode() == KeyCode.ENTER || event.getCode() == KeyCode.TAB) {
passWord.requestFocus();
}
}
I think you'll need to compile a more complete example. Eg maybe a simple fxml and where it goes wrong. Here is an example that works, and it uses most of the ingredients you are.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.scene.input.KeyEvent;
public class TextFields extends Application{
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("text field");
TextField a = new TextField();
TextField b = new TextField();
a.setOnKeyPressed( evt ->{
System.out.println(KeyCode.ENTER + ", " + evt.getCode());
if(evt.getCode().equals(KeyCode.ENTER)){
System.out.println("entered");
b.requestFocus();
}
});
BorderPane root = new BorderPane();
root.setLeft(a);
root.setRight(b);
primaryStage.setScene(new Scene(root, 300, 100));
primaryStage.show();
}
}
This code creates a frame with 2 text fields, if you press enter in the left one, you will move to the right one.
I have a ChoiceBox and I want to refresh it's content whenever user expands it. I haven't found a proper listener for this. All the stuff google gives is related to handling ChangeValue events.
I reckon I should add eventListener<ActionEvent> to ChoiceBox since what I'm handling is click on a ChoiceBox, but my implementation doesn't work.
ActionEvent fires when I click on any List value, not when I click ChoiceBox itself.
Register a listener with the choice box's showingProperty:
choiceBox.showingProperty().addListener((obs, wasShowing, isNowShowing) -> {
if (isNowShowing) {
// choice box popup is now displayed
} else {
// choice box popup is now hidden
}
});
Here is a quick demo:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ChoiceBoxPopupTest extends Application {
private int nextValue ;
#Override
public void start(Stage primaryStage) {
ChoiceBox<Integer> choiceBox = new ChoiceBox<>();
choiceBox.getItems().add(nextValue);
choiceBox.setValue(nextValue);
choiceBox.showingProperty().addListener((obs, wasShowing, isNowShowing) -> {
if (isNowShowing) {
choiceBox.getItems().setAll(++nextValue, ++nextValue, ++nextValue);
}
});
BorderPane root = new BorderPane();
root.setTop(choiceBox);
BorderPane.setAlignment(choiceBox, Pos.CENTER);
root.setPadding(new Insets(5));
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
How to requestFocus on TextField of different Tabs of TabPane, whenever the Enter Key is pressed on that particular Tab.
Each Tab within TabPane contains TextField, whenever a particular Tab is selected using Enter Key, than the TextField within that Tab must get Focused (requestFocus)
package tabdemo;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TabDemo extends Application {
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setPrefHeight(500);
VBox.setVgrow(tabPane, Priority.ALWAYS);
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
tabPane.setStyle("-fx-background-color: #fff; -fx-border-color: #e7eaec #e7eaec #e7eaec #e7eaec; -fx-border-width: 6;");
Tab tab1 = new Tab();
tab1.setText(" Try Demo");
tab1.setId("TryDemo");
TextField username1 = new TextField();
tab1.setContent(username1);
Tab tab2 = new Tab();
tab2.setText(" Select Company");
tab2.setId("SelectCompany");
TextField username2 = new TextField();
tab2.setContent(username2);
Tab tab3 = new Tab();
tab3.setText(" Create Company");
tab3.setId("CreateCompany");
TextField username3 = new TextField();
tab3.setContent(username3);
//Add childen to tabpane
tabPane.getTabs().addAll(tab1, tab2, tab3);
StackPane root = new StackPane();
root.getChildren().add(tabPane);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
// Tabpane Change Listener
tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
#Override
public void changed(ObservableValue<? extends Tab> arg0, Tab oldtab, Tab newtab) {
if (newtab == tab1) {
}
if (newtab == tab2) {
}
if (newtab == tab3) {
//tab3.getContent().requestFocus();
//username3.requestFocus();
}
}
});
// End Tabpane Change Listener
// Root Listner
root.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.TAB || event.getCode() == KeyCode.ENTER) {
tabPane.requestFocus();
event.consume();
}
}
});
// END Root Listner
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Any help would be appreciated.
Change your implementation of the ChangeListener to this:
// Tabpane Change Listener
tabPane.getSelectionModel().selectedItemProperty().addListener((arg0, oldtab, newtab) -> {
TextField field = (TextField) newtab.getContent();
Platform.runLater(() -> field.requestFocus());
});
This ensures that the request for the focus is pushed as the last 'task' for the application thread.
See also RequestFocus in TextField doesn't work -JavaFX 2.1 and JavaFX: Focusing textfield programmatically
I am a novice on JavaFX.
Recently I was trying to modify the code by jewelsea found on this link :
https://gist.github.com/jewelsea/4989970#file-promptingtaskdemo-java-L87
On the code above, the program pauses a FutureTask with a dialog.showAndWait() method.
I was trying to pause a Task using something else so I commented out the showAndWait(), and added a button with this code
Platform.runLater(task);
try {
task.get();
} catch(ExecutionException ee) {}
catch(InterruptedException ie) {}
in its .setOnAction(), but it crashes the application everytime the button is pressed, any help will really be appreciated.
public class PromptingTaskDemo extends Application {
private static final String[] SAMPLE_TEXT =
"MISSING Lorem ipsum dolor sit amet MISSING consectetur adipisicing elit sed do eiusmod tempor incididunt MISSING ut labore et dolore magna aliqua"
.split(" ");
#Override public void start(Stage primaryStage) {
Label status = new Label();
ProgressBar progress = new ProgressBar();
Button pauseButton = new Button("Pause");
VBox textContainer = new VBox(10);
textContainer.setStyle("-fx-background-color: burlywood; -fx-padding: 10;");
LoadTextTask task = new LoadTextTask(SAMPLE_TEXT, textContainer);
status.textProperty().bind(task.messageProperty());
progress.progressProperty().bind(task.progressProperty());
final Thread taskThread = new Thread(task, "label-generator");
taskThread.setDaemon(true);
pauseButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Platform.runLater(task);
try {
task.get();
} catch(ExecutionException ee) {}
catch(InterruptedException ie) {}
}
});
VBox layout = new VBox(10);
layout.getChildren().addAll(status, progress, pauseButton, textContainer);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
primaryStage.setScene(new Scene(layout, 300, 700));
primaryStage.show();
taskThread.start();
}
public static void main(String[] args) { launch(args); }
}
class LoadTextTask extends Task<Void> {
private final String[] lines;
private final Pane container;
private final IntegerProperty idx = new SimpleIntegerProperty(0);
FutureTask<String> futureTask;
LoadTextTask(final String[] lines, final Pane container) {
this.lines = lines;
this.container = container;
}
#Override protected Void call() throws Exception {
try {
updateProgress(0, lines.length);
while (idx.get() < lines.length) {
final Label nextLabel = new Label();
final int curIdx = idx.get();
updateMessage("Reading Line: " + curIdx);
String nextText = lines[curIdx];
if ("MISSING".equals(nextText)) {
updateMessage("Prompting for missing text for line: " + curIdx);
futureTask = new FutureTask(
new MissingTextPrompt(
container.getScene().getWindow()
)
);
Platform.runLater(futureTask);
nextText = futureTask.get();
nextLabel.setStyle("-fx-background-color: palegreen;");
}
nextLabel.setText(nextText);
Platform.runLater(
new AddNodeLater(
container,
curIdx,
nextLabel
)
);
idx.set(curIdx + 1);
updateProgress(curIdx + 1, lines.length);
Thread.sleep(200);
}
updateMessage("Loading Text Completed: " + idx.get() + " lines loaded");
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
class MissingTextPrompt implements Callable<String> {
final Window owner;
public Button pauseButton = new Button("Pause");
MissingTextPrompt(Window owner) {
this.owner = owner;
}
#Override public String call() throws Exception {
final Stage dialog = new Stage();
dialog.setTitle("Enter Missin Text");
dialog.initOwner(owner);
dialog.initStyle(StageStyle.UTILITY);
dialog.initModality(Modality.WINDOW_MODAL);
final TextField textField = new TextField();
final Button submitButton = new Button("Submit");
submitButton.setDefaultButton(true);
submitButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent t) {
dialog.close();
}
});
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER_RIGHT);
layout.setStyle("-fx-background-color: azure; -fx-padding: 10;");
layout.getChildren().setAll(textField, submitButton);
dialog.setScene(new Scene(layout));
//dialog.showAndWait();
return textField.getText();
}
}
class AddNodeLater implements Runnable {
final Pane container;
final Node node;
final int idx;
public AddNodeLater(final Pane container, final int idx, final Node node) {
this.container = container;
this.node = node;
this.idx = idx;
}
#Override public void run() {
container.getChildren().add(idx, node);
}
}
}
I have this very simple example of GridPane.
GridPane playerGrid = new GridPane();
Text title = new Text("Top Scorers in English Premier League");
title.setFont(Font.font("Arial", FontWeight.BOLD, 20));
playerGrid.add(title, 0,0,4,1);
How I can select the text with the mouse and copy it when the program is running?
Text nodes in JavaFX are not selectable.
If you want to have text selectable, use a selection aware control.
The fact that the text is eventually placed in a GridPane is irrelevant to this question.
For example, use a read only TextField:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class SelectableTextSample extends Application {
#Override public void start(final Stage stage) throws Exception {
stage.setScene(
new Scene(
new SelectableText(
"Top Scorers in English Premier League"
)
)
);
stage.show();
}
class SelectableText extends TextField {
SelectableText(String text) {
super(text);
setEditable(false);
setPrefColumnCount(20);
}
}
public static void main(String[] args) {
Application.launch(args);
}
}
Alternate solution
You could use a WebView if you wish. For some situations that may be a better solution, but for others it may not.