I have a DatePicker with the following code :
datepicker.getEditor().addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
datepicker.show();
}
);
When clicked on the textfield, the popup appears.
Datepicker popup open
The problem is that i can't type a number in the textfield when the popup is shown.
is it a problem of focus ?
thanks for your help.
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Skin;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class ExampleDatePicker extends Application {
public static void main(final String[] args) {
launch(args);
}
private DatePicker datepicker;
#Override
public void start(final Stage primaryStage) {
final StackPane stackPane = new StackPane();
this.datepicker = new DatePicker() {
#Override
protected Skin<?> createDefaultSkin() {
final DatePickerSkin datePickerSkin = (DatePickerSkin) super.createDefaultSkin();
datePickerSkin.getPopupContent().setOnKeyTyped(new EventHandler<KeyEvent>() {
#Override
public void handle(final KeyEvent ke) {
ExampleDatePicker.this.setText(ke.getCharacter());
}
});
return datePickerSkin;
}
};
this.datepicker.addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
this.datepicker.show();
});
stackPane.getChildren().add(this.datepicker);
primaryStage.setScene(new Scene(stackPane, 400.0, 200.0));
primaryStage.show();
}
public void setText(final String string) {
this.datepicker.getEditor().setText(this.datepicker.getEditor().getText() + string);
}}
As I understand it, you can select a date from the popup, but you can't type anything in the textbox manually. It's editable problem.
In FXML, add editable="true" to your TextField tag. Or check the "Editable" checkbox in Scene Builder. I hope so it can help to you.
Have a nice coding :)
Related
I have a very simple problem, which I can't find in any other posts :
In javafx15 / java15.0.1, I am trying to click a Checkbox while pressing, for example, the CONTROL key... State is not changing.
I tried to catch the key (with a key event on the checkbox), and I do catch the control key pressed... But state of checkbox just does not change if a key is pressed simultaniously.
How to get this to just work in a transparent way ?
Here is a most basic simple code to illustate the problem :
package checkboxkeypressed;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;
public class CheckboxWhileKeyPressedNotWorking extends Application {
private CheckBox checkbox = new CheckBox();
#Override
public void start(Stage primaryStage) {
checkbox.setText("Click me while pressing a key...");
Scene scene = new Scene(checkbox, 200, 50);
primaryStage.setTitle("Checkbox cannot be ticked while a key is pressed !!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Any help would be greatly appreciated.
Improving on the solution offered by etuygar:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;
public class CheckboxWhileKeyPressedNotWorking extends Application {
private final CheckBox checkbox = new CheckBox();
private boolean isControlKeyDown = false;
#Override
public void start(Stage primaryStage) {
checkbox.setText("Click me while pressing <CNTRL> key");
checkbox.setOnMouseClicked(e->{
if(isControlKeyDown){
checkbox.fire(); //change check box state
}
});
Scene scene = new Scene(checkbox, 300, 50);
scene.setOnKeyPressed(keyEvent -> {
isControlKeyDown = keyEvent.isControlDown();
});
scene.setOnKeyReleased(keyEvent -> {
isControlKeyDown = keyEvent.isControlDown();
});
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You can do something like this.
package checkboxkeypressed;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.input.KeyCode;
import javafx.stage.Stage;
public class CheckboxWhileKeyPressedNotWorking extends Application {
private CheckBox checkbox = new CheckBox();
private boolean ctrlOk, lastState;
#Override
public void start(Stage primaryStage) {
checkbox.setText("Click me while pressing a key...");
Scene scene = new Scene(checkbox, 200, 50);
scene.setOnKeyPressed(event -> {
if (event.getCode() == KeyCode.CONTROL) ctrlOk = true;
});
scene.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.CONTROL) ctrlOk = false;
});
checkbox.setOnMouseClicked(event -> {
if (!ctrlOk) {
checkbox.setSelected(lastState);
} else {
checkbox.setSelected(!checkbox.isSelected());
lastState = checkbox.isSelected();
}
});
primaryStage.setTitle("Checkbox cannot be ticked while a key is pressed !!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Thank you soooooo much #miss-chanandler-bong !
So would this answer be ok ? I'm forcing the checkbox to be armed, when armed is changing...
package checkboxkeypressed;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class CheckboxWhileKeyPressed extends Application {
private CheckBox checkbox = new CheckBox();
#Override
public void start(Stage primaryStage) {
checkbox.setText("Click me while pressing a key...");
checkbox.armedProperty().addListener(changeListener -> checkbox.arm());
checkbox.arm();
checkbox.setOnKeyPressed(keyEvent -> processKeyPressed(keyEvent));
Scene scene = new Scene(checkbox, 200, 50);
primaryStage.setTitle("Checkbox CAN NOW be ticked while a key is pressed !!");
primaryStage.setScene(scene);
primaryStage.show();
}
private void processKeyPressed(KeyEvent keyEvent) {
if (keyEvent.getCode().equals(KeyCode.CONTROL)) {
System.out.println("Key IS control");
} else {
System.out.println("Key IS NOT control : '" + keyEvent.getCode().getName() + "'");
}
}
public static void main(String[] args) {
launch(args);
}
}
i have a textfield with autocomplete and i want to show button near each item appeared into that list
this is my code
List<String> s = ms.getUsernames(ms.getUser(7).getListamis());
TextFields.bindAutoCompletion(txtsearch, s);
this is the method getusernames
public List<String> getUsernames(String list_amis) {
List<String> ls = new ArrayList<>();
String [] idmember = list_amis.split("/");
for (String i : idmember) {
ls.add(getUser(Integer.parseInt(i)).getUsername());
}
return ls;
}
this is my output
i want to add a button near testing as a result i can get its ID
This is the solution I came up with. There certainly is a better way that is more elegant and works better, but I guess this would work for many situations. You would have to do something about the size of the ListView, though, and I didn't test this in an environment in which the appearing ListView might change something about the design of the rest of the UI. I suggest putting the whole thing into a PopOver or something.
import java.util.function.Predicate;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class NewFXMain extends Application {
#Override
public void start(Stage primaryStage) {
ObservableList<String> list = FXCollections.observableArrayList("one","two","three");
FilteredList<String> filteredList = new FilteredList<>(list);
VBox box = new VBox();
TextField textField = new TextField();
textField.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
filteredList.setPredicate(new Predicate<String>() {
#Override
public boolean test(String s){
return s.toLowerCase().contains(newValue.toLowerCase());
}
});
}
});
ListView listView = new ListView();
listView.setItems(filteredList);
listView.visibleProperty().bind(textField.textProperty().isNotEmpty());
listView.setCellFactory(new Callback() {
#Override
public Object call(Object param) {
ListCell cell = new ListCell(){
#Override
public void updateItem(Object item, boolean empty){
if(item != null && !empty){
super.updateItem(item, empty);
HBox contentBox = new HBox();
Label label = new Label(item.toString());
Button button = new Button("delete");
HBox separator = new HBox();
HBox.setHgrow(separator, Priority.ALWAYS);
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println(item);
}
});
contentBox.getChildren().addAll(label, separator, button);
setGraphic(contentBox);
}else{
setText(null);
setGraphic(null);
}
}
};
return cell;
}
});
box.getChildren().addAll(textField,listView);
StackPane root = new StackPane();
root.getChildren().add(box);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Autocomplete");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I am using JFoenix in my new JavaFX Application. I've successfully created my own message dialog.
package Dialog;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialogLayout;
import com.jfoenix.controls.events.JFXDialogEvent;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
public class OK_Message extends JFXDialog {
private StackPane Container;
private JFXDialogLayout Content;
String DialogText;
String Headline;
JFXButton btn;
boolean OK = false;
private BooleanProperty okval;
public OK_Message(
StackPane Container,
String Headline,
String DialogText
){
this.Container = Container;
this.DialogText = DialogText;
this.Headline = Headline;
}
public void ShowDialog(){
setDialogContainer(Container);
setContent(getDialogContent());
setTransitionType(JFXDialog.DialogTransition.TOP);
setOverlayClose(false);
setFocusTraversable(true);
setOnDialogOpened((JFXDialogEvent event) -> {
Platform.runLater(()->{
btn.requestFocus();
});});
setOnKeyPressed((KeyEvent e)->{
e.consume();
if(e.getCode()== KeyCode.ENTER){close();}
else if(e.getCode()== KeyCode.SPACE){btn.requestFocus();}
else{}
});
show();
}
private JFXDialogLayout getDialogContent(){
Content = new JFXDialogLayout();
Content.setHeading(HeadLine());
Content.setBody(Body());
// Platform.runLater(()->{b.requestFocus();});
Content.setActions(getButton());
return Content;
}
private Label HeadLine(){
Label l = new Label(Headline);
l.setFont(new Font(18));
return l;
}
private GridPane Body(){
Label l = new Label(DialogText);
l.setFont(new Font(14));
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(8);
GridPane.setConstraints(l, 0, 0, 1, 1, HPos.LEFT, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS, new Insets(0, 0, 0, 0));
grid.getChildren().addAll(l);
return grid;
}
private JFXButton getButton(){
btn = new JFXButton("OK");
btn.setButtonType(JFXButton.ButtonType.FLAT);
btn.setPrefWidth(50);
btn.setTextFill(Color.WHITE);
btn.setOnAction((ActionEvent event) -> {
CloseDialog();
});
btn.setStyle("-fx-background-color:#FFFFFF");
btn.focusedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if(newValue){
btn.setStyle("-fx-background-color:red");
}
}
});
return btn;
}
private void CloseDialog(){
close();
}
}
Now I can call my dialog anywhere: like this:
Dialog.OK_Message message =
new Dialog.OK_Message((StackPane)app_setup.getParent(),
"Message",
"Changes will be affected after restart.");
message.ShowDialog();
I cannot find a way to detect if use has clicked the button or not. Or what key is pressed by the user. If the user has clicked the OK Button I want to do something. Or if the use has pressed some key I want to do some other thing ? How can I listen to the above dialog ?
You can use setOnKeyPressed on your OK_Message class just like you used inside your class since it is extending the JFXDialog.
message.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
System.out.println(event.getCode().getName());
}
});
For listening which button is clicked why not create customEventListenerfor your OK_Message class?
In your OK_Message.java file create an interface outside of the class like;
interface OnEventListener {
void onButtonCliked(String id);
}
and add a new method to your OK_Message class as
public void setOnEventListener(OnEventListener listener) {
mOnEventListener = listener;
}
First
Lets change your getButton() method to this one to add functionality of creating multiple buttons with different IDs and texts.
private JFXButton getButton(String id,String text){
JFXButton btn = new JFXButton(text);
btn.setId(id);
btn.setButtonType(JFXButton.ButtonType.FLAT);
btn.setPrefWidth(50);
btn.setTextFill(Color.WHITE);
btn.setOnAction((ActionEvent event) -> {
mOnEventListener.onButtonCliked(btn.getId()); //Here we are firing the event
CloseDialog();
});
btn.setStyle("-fx-background-color:red");
return btn;
}
In getDialogContent() lets create more than one button.
Content.setActions(getButton("Button1","OK"),getButton("Button2","CANCEL"));
Now you can use listeners after declaring new OK_Message objects
OK_Message message =
new OK_Message((StackPane)stackpane,
"Message",
"Changes will be affected after restart.");
message.ShowDialog();
message.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
System.out.println(event.getCode().getName());
}
});
message.setOnEventListener(new OnEventListener() {
#Override
public void onButtonCliked(String id) {
System.out.println(id);
}
});
Determine what do to according to the id observed by onButtonClicked() function.
I have an internal jfxtra window. On clicking a button, I want to bring it forward.
The code that I have tried :
window w = new window("mdi win");
private Stage primaryStage;
private BorderPane rootLayout;
...
public void win() {
Parent bla = FXMLLoader.load(getClass().getResource("bla.fxml"));
w.getContentPane().getChildren().add(bla);
rootLayout.getChildren().add(w);
}
private void wfront(ActionEvent event) throws Exception {
w.isMoveToFront(); // is not?
}
How to make it possible?
So you made me curious and I went through the JFXtras docs. I came to know that Window in Jfxtras extends Control. So there is a method called toFront which can be fired on it. To show this I have created a sample for you.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import jfxtras.scene.control.window.Window;
public class NewWindow extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
StackPane stackPane = new StackPane();
Button button = new Button("Click Me to show Window !");
Window window = new Window("Cick Me to bring me to front");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
window.toFront();
window.setTitle("I am on the Front");
}
});
window.setPrefSize(200, 200);
stackPane.getChildren().addAll(window, button);
Scene scene = new Scene(stackPane, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Let me know, if you are looking for something else !
I did implement a popup window in a new stage and I'm now trying to close it, no matter where I click (excluding the popup itself). This works just fine. Although the popup windows disappears when I click on another element (e.g. a button) on the background, I'd still like to get the event for the button. Any suggestions on how to achieve this? I put together a short example of the situation.
package application;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
// the popup
Pane p = new Pane();
p.setPrefSize(100, 100);
p.setStyle("-fx-background-color: #660066");
final Stage popUp = new Stage();
Scene popUpScene = new Scene(p);
popUp.setScene(popUpScene);
Button btnShow = new Button("Show popUp");
root.setCenter(btnShow);
btnShow.setOnMouseClicked(new EventHandler<Event>() {
#Override
public void handle(Event event) {
ChangeListener stageFocusListener = new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue) {
if (!newPropertyValue) {
popUp.hide();
}
}
};
popUp.focusedProperty().addListener(stageFocusListener);
popUp.show();
}
});
Button btnTest = new Button("test");
root.setRight(btnTest);
btnTest.setOnMouseClicked(new EventHandler<Event>() {
#Override
public void handle(Event event) {
System.out.println("Button test clicked");
}
});
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
You can put the hiding event to the queue without disturbing the event handling procedure of the button
if (!newPropertyValue) {
Platform.runLater(new Runnable() {
#Override
public void run() {
popUp.hide();
}
});
}