When there is no record in any table it shows a message 'No content in table', which is by default functionality of TableView in JavaFx.
So here my question is, does the same can be possible with ListView in JavaFx ? Like, if there is no item in any ListView then it will show a message same as TableView, instead of a blank/empty fields.
You have to try this:-
listView.setPlaceholder(new Label("No Content In List"));
its 100% working....
JavaFX8 has a setPlaceholder(...) method for ListView.
In earlier versions, you need to roll your own somehow. This is a bit of a hack: it wraps the ListView in a stack pane, with a white rectangle and the placeholder displayed over the top of the list view. The placeholder and rectangle have their visible property bound, so they are only visible if the list is empty.
There may be easier ways that I'm not seeing right away...
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class ListViewPlaceholderTest extends Application {
#Override
public void start(Stage primaryStage) {
final ListView<String> listView = new ListView<>();
final IntegerProperty counter = new SimpleIntegerProperty();
final Button addButton = new Button("Add item");
addButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
counter.set(counter.get()+1);
listView.getItems().add("Item "+counter.get());
}
});
final Button removeButton = new Button("Remove");
removeButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
listView.getItems().remove(listView.getSelectionModel().getSelectedIndex());
}
});
removeButton.disableProperty().bind(Bindings.equal(listView.getSelectionModel().selectedIndexProperty(), -1));
final HBox buttons = new HBox(5);
buttons.setPadding(new Insets(10));
buttons.getChildren().addAll(addButton, removeButton);
final BorderPane root = new BorderPane();
root.setCenter(createPlaceholderForListView(listView, new Label("No content in List")));
root.setBottom(buttons);
final Scene scene = new Scene(root, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private Node createPlaceholderForListView(ListView<?> listView, Node placeholder) {
final StackPane pane = new StackPane();
final Rectangle rect = new Rectangle(0, 0, Color.WHITE);
rect.widthProperty().bind(listView.widthProperty());
rect.heightProperty().bind(listView.heightProperty());
pane.getChildren().addAll(listView, rect, placeholder);
placeholder.visibleProperty().bind(Bindings.isEmpty(listView.getItems()));
rect.visibleProperty().bind(placeholder.visibleProperty());
rect.setMouseTransparent(true);
return pane ;
}
}
With fxml:
<ListView fx:id="foundContentList">
<placeholder>
<Label text="Nothing found" />
</placeholder>
</ListView>
Not entirely sure but I don't think there is a setPlaceholder method(to set the default message when no content in table) for ListView.
The workaround that I use is to create an Object in the list that indicate "No content" and show that on the listview and also disable it.
For example:
ObservableList noContent= FXCollections.observableArrayList("No content found");
ListView listView = new ListView(noContent);
listView.setDisable(true);
Related
Is there a way to display an integer on the slider thumb in javafx? Just curious because I am trying to make a clean UI and cannot find anything on displaying an integer on the slider thumb.
One way to address the requirement is by accessing the thumb node and include a Text/Label node. Please check the below demo for what i mean.
You can adjust the thumb padding and the text size for fine tuning.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class SliderTextDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Slider slider = new Slider(1, 10, 3);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(1f);
slider.setBlockIncrement(1f);
slider.setSnapToTicks(true);
Text text = new Text();
slider.skinProperty().addListener((obs,old,skin)->{
if(skin!=null){
StackPane thumb = (StackPane)slider.lookup(".thumb");
thumb.setPadding(new Insets(10));
thumb.getChildren().add(text);
}
});
slider.valueProperty().addListener((obs,old,val)->text.setText(val.intValue()+""));
slider.setValue(2);
VBox root = new VBox(slider);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(20));
root.setSpacing(20);
Scene scene = new Scene(root,600,200);
primaryStage.setScene(scene);
primaryStage.setTitle("Slider Text Demo");
primaryStage.show();
}
}
UPDATE:
If you don't want to rely on accessing the skin,you can indeed implement/initialize the Slider as below. That way you can create a custom Slider and can reuse in multiple places.
Slider slider = new Slider(1, 10, 3) {
Text text;
#Override
protected void layoutChildren() {
super.layoutChildren();
if (text == null) {
text = new Text(((int) getValue()) + "");
valueProperty().addListener((obs, old, val) -> text.setText(val.intValue() + ""));
StackPane thumb = (StackPane) lookup(".thumb");
thumb.setPadding(new Insets(10));
thumb.getChildren().add(text);
}
}
};
Is it possible to use a Node as a mouse cursor? I'm thinking in a ProgressIndicator. For example a determinate one, letting the user know how much percentage of the current task is done.
Probably the most reliable way to do this is to set the cursor to Cursor.NONE, and have a label with the progress indicator as its graphic, which tracks the mouse coordinates.
I tried using an ImageCursor which updated, but nothing appeared: I am guessing the images couldn't be computed quickly enough.
Here's an SSCCE of the first technique:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.ImageCursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class ProgressIndicatorAsCursor extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Start");
Service<Void> service = new Service<Void>() {
#Override
public Task<Void> createTask() {
return new Task<Void>() {
#Override
public Void call() throws Exception {
for (int i = 1 ; i <= 1000; i++) {
Thread.sleep(10);
updateProgress(i, 1000);
}
return null ;
}
};
}
};
button.disableProperty().bind(service.runningProperty());
button.setOnAction(e -> service.restart());
ProgressIndicator pi = new ProgressIndicator();
pi.progressProperty().bind(service.progressProperty());
Pane pane = new Pane();
// fill pane with rectangle as task progresses:
Rectangle rectangle = new Rectangle();
rectangle.setFill(Color.CORNFLOWERBLUE);
rectangle.setX(0);
rectangle.widthProperty().bind(pane.widthProperty());
rectangle.heightProperty().bind(pane.heightProperty().multiply(service.progressProperty()));
rectangle.yProperty().bind(pane.heightProperty().subtract(rectangle.heightProperty()));
pane.getChildren().add(rectangle);
Label label = new Label();
label.graphicProperty().bind(
Bindings.when(service.runningProperty())
.then(pi)
.otherwise((ProgressIndicator)null));
pane.setOnMouseEntered(e ->
pane.getChildren().add(label));
pane.setOnMouseExited(e ->
pane.getChildren().remove(label));
pane.setOnMouseMoved(e -> label.relocate(e.getX(), e.getY()));
pane.cursorProperty().bind(
Bindings.when(service.runningProperty())
.then(Cursor.NONE)
.otherwise(Cursor.DEFAULT));
BorderPane.setAlignment(button, Pos.CENTER);
BorderPane.setMargin(button, new Insets(10));
BorderPane root = new BorderPane(pane, new Rectangle(0,0,0,20), null, button, null);
primaryStage.setScene(new Scene(root, 400, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Sees it's impossible, but you could obtain the cursor property and keep updating it with an image as your desire.
I was wondering how to make the caret visible and/or flash whilst using a TextField or TextArea. The ones I have created in my GUI work as the letters appear when typed but there is no visible caret.
I've looked through the TextField documentation but none are about making it visible or not. I expected to find something along the lines "setCaretVisible(Boolean);"
Do I have to make it visible via CSS? If so, any suggestions would be most welcome!
Please see code that I've quickly put together to illustrate the problem:
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Test extends Application {
public static void main(String[] arguments) { launch(arguments); }
#Override public void start(Stage stage) {
Scene scene = new Scene(new Group());
scene.setRoot(new BuildLayout(stage));
stage.setTitle("Application Name");
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setFullScreen(true);
stage.setFullScreenExitHint("");
stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
stage.show();
}
}
final class BuildLayout extends BorderPane {
protected BuildLayout(Stage stage) {
TabPane tabpane = new TabPane();
Tab tab = new Tab();
tab.setGraphic(new Text("Video Browser"));
tab.setClosable(false);
tab.setContent(new Input(1));
tabpane.getTabs().addAll(tab);
setTop(new Toolbar(stage));
setCenter(tabpane);
}
}
final class Input extends VBox {
Input(int id) {
HBox hbox = new HBox();
TextField videoTitle = new TextField("video_title");
TextArea description = new TextArea( "video_description");
Button share = new Button("share");
Button unshare = new Button("unshare");
setPadding(new Insets(5,10,10,5));
setAlignment(Pos.TOP_CENTER);
hbox.getChildren().addAll(videoTitle, new Text(" Creator: " + " Date: " + " Views: " + " "));
if(true) {
videoTitle.setEditable(true);
description.setEditable(true);
if(true) {
hbox.getChildren().add(share);
} else { hbox.getChildren().add(unshare); }
}
getChildren().addAll(hbox, description);
}
}
final class Toolbar extends HBox {
protected Toolbar(Stage stage) {
Button close = new Button("close");
close.setOnAction((ActionEvent e) -> { stage.close(); });
setAlignment(Pos.CENTER_LEFT);
getChildren().addAll(close);
}
}
Many thanks,
This problem only occurs on Mac and not Windows (untested Linux). The fix is to downgrade to a JavaFX 2.2 compliant maximised window as the setMaximized() from JavaFX 8 also isn't Mac compatible.
Modifying the start method with some code found here:
#Override public void start(Stage stage) {
Scene scene = new Scene(new Group());
scene.setRoot(new BuildLayout(stage));
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
stage.setTitle("Application Name");
stage.setScene(scene);
stage.setX(bounds.getMinX());
stage.setY(bounds.getMinY());
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.show();
}
Produces a fullscreen application with visible and flashing caret.
I have textfield that containing a value and that value should be Right alignment.
When i run the application it display the text left alignment but i set the Right alignment.
and problem with 3rd textfield.
After clicking the update button it works fine.
So may i know why it is behave different.
Code:
import java.io.File;
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.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class TextFieldAlignment extends Application {
TextField rText;
File file;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
rText = new TextField("updated right1 updated right2 updated right3 updated right4");
rText.setAlignment(Pos.CENTER_RIGHT);
Button btn = new Button("update");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
rText.setText("updated right1 updated right2 updated right3 updated right4");
// applyWorkaround();
}
});
final Label labelFile = new Label();
Button btn2 = new Button();
btn2.setText("Open FileChooser'");
btn2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("AVI files (*.exml)", "*.exml");
fileChooser.getExtensionFilters().add(extFilter);
//Show open file dialog
file = fileChooser.showOpenDialog(null);
// rText.setText(file.getPath());
}
});
VBox root = new VBox();
root.getChildren().addAll(rText, btn, btn2);
stage.setScene(new Scene(root, 200, 300));
stage.show();
}
}
Put the setalignment and settext after you add the TextField to the Scene.
Ref: Java API docs for Node
Node objects may be constructed and modified on any thread as long
they are not yet attached to a Scene. An application must attach nodes
to a Scene, and modify nodes that are already attached to a Scene, on
the JavaFX Application Thread.
I've made my own TimePicker that is supposed to work very much like DatePicker. I would like to know the best way to handle an event such as selecting a time and confirming it from the PopupWindow.
I could:
Make my TimePicker's popup node (a separate FXML and controller) define an interface and force the TimePicker parent to implement the methods to handle the selected date. (I'd MUCH like to avoid using interfaces in this manner. It seems like a terribly way to do things.)
Register some kind of custom EventHandler and listener to the popup window? Then, if I click OKAY after selecting a date from the PopupWindow, an event can be fired all the way up to the TimePicker.
Implement some kind of callback-like function. In android, for example, there were options for going to another screen solely to retrieve a result. I'm not sure if JavaFX has that kind of thing. The screens are quite separated from each other.
Just expose a ReadOnlyProperty representing the value. The user of your popup can then just observe the property.
Here's a proof of concept using a DatePicker:
import java.time.LocalDate;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Popup;
import javafx.stage.PopupWindow;
import javafx.stage.Stage;
public class DatePickerPopupExample extends Application {
#Override
public void start(Stage primaryStage) {
Label dateLabel = new Label(LocalDate.now().toString());
Button changeButton = new Button("Change");
HBox root = new HBox(5, dateLabel, changeButton);
root.setAlignment(Pos.CENTER);
changeButton.setOnAction(event -> {
DatePickerPopup popup = new DatePickerPopup();
popup.valueProperty().addListener((obs, oldDate, newDate) -> {
dateLabel.setText(newDate.toString());
});
Bounds buttonBds = changeButton.getBoundsInLocal();
Point2D loc = changeButton.localToScreen(buttonBds.getMaxX(), buttonBds.getMinY());
popup.showPopup(primaryStage, loc.getX(), loc.getY());
});
Scene scene = new Scene(root, 250, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public class DatePickerPopup {
private final ReadOnlyObjectWrapper<LocalDate> value = new ReadOnlyObjectWrapper<>();
private final Popup popup ;
public ReadOnlyObjectProperty<LocalDate> valueProperty() {
return value.getReadOnlyProperty();
}
public final LocalDate getValue() {
return valueProperty().get();
}
public DatePickerPopup(LocalDate date) {
value.set(date);
DatePicker picker = new DatePicker(date);
Button okButton = new Button("OK");
okButton.setOnAction(event -> {
popup.hide();
value.set(picker.getValue());
});
Button cancelButton = new Button("Cancel");
cancelButton.setOnAction(event -> {
popup.hide();
});
BorderPane root = new BorderPane();
root.setCenter(picker);
HBox buttons = new HBox(5, okButton, cancelButton);
buttons.setPadding(new Insets(5));
buttons.setAlignment(Pos.CENTER);
root.setBottom(buttons);
popup = new Popup();
popup.getContent().add(root);
}
public DatePickerPopup() {
this(LocalDate.now());
}
public void showPopup(Stage owner, double x, double y) {
popup.show(owner, x, y);
}
}
public static void main(String[] args) {
launch(args);
}
}