TextField f = new TextField();
Button b = new Button("Save");
b.setClickShortcut(KeyCode.ENTER); // For quick saving from text field itself
TextArea longText = new TextArea(); // "Enter" is garbled here
Hot to make the shortcut to work only in the from text field?
Use focus and blur listeners to remove and add the shortcut key:
f.addFocusListener(new FocusListener() {
#Override
public void focus(FocusEvent event) {
b.setClickShortcut(KeyCode.ENTER);
}
});
f.addBlurListener(new BlurListener() {
#Override
public void blur(BlurEvent event) {
b.removeClickShortcut();
}
});
Newer versions of Vaadin require the following code as addListener() is deprecated now.
f.addFocusListener(new FocusListener() {
private static final long serialVersionUID = -6733373447805994139L;
#Override
public void focus(FocusEvent event) {
b.setClickShortcut(KeyCode.ENTER);
}
});
f.addBlurListener(new BlurListener() {
private static final long serialVersionUID = -3673311830300629513L;
#Override
public void blur(BlurEvent event) {
b.removeClickShortcut();
}
});
Talking in terms of Vaadin 14,
I was looking for the answer and for me, this worked well
Button search = new Button("Search");
search.addClickShortcut(Key.ENTER);
As of Vaadin 23 (and probably for sometime before) the requirements have changed again.
private ShortcutRegistration primaryShortCut;
void customShortCutHandling()
{
myTextAreaField.addFocusListener((e) ->
{
System.out.println("disable");
primaryShortCut = primaryButton.addClickShortcut(Key.ENTER);
});
myTextAreaField.addBlurListener((e) ->
{
System.out.println("enable");
primaryShortCut.remove();
});
}
}
This code assumes that primaryShortCut was set when the form is created.
Related
I have created a text field:
TextField tfPost = new TextField("140 character word count...");
I also have a button with a ActionEvent Handler class:
Button btTweet = new Button("Tweet");
TweetHandlerClass btTweetHandler = new TweetHandlerClass();
btTweet.setOnAction(btTweetHandler);
Here is the body of the handler class:
class TweetHandlerClass implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent ae) {
System.out.println("Tweet button was clicked");
String newTweet = tfPost.getText();
}
}
What I need is for the string inside the TextField to be saved to a string variable when the Tweet button is clicked. How do I do this?
Variable scoping is a design question. The OP's question does not provide sufficient information to understand the full use case. One approach is to store the variable in the TweetHandlerClass. There are various rationales for and against such an approach. Nonetheless, for the specific question posed, it should suffice.
class TweetHandlerClass implements EventHandler<ActionEvent> {
private final TextField tfPost;
public TweetHandlerClass(TextField srcTxtFld)
{
this.tfPost = srcTxtFld;
}
#Override
public void handle(ActionEvent ae) {
System.out.println("Tweet button was clicked");
String newTweet = tfPost.getText();
}
}
Then, in the instantiating the Button:
TextField tfPost = new TextField("140 character word count...");
Button btTweet = new Button("Tweet");
TweetHandlerClass btTweetHandler = new TweetHandlerClass(tfPost);
btTweet.setOnAction(btTweetHandler);
If you really want the event handler to be a top-level class like that, you could give it a reference to a TextField as in #KevinO's answer. A slight variant on that would just be to have a reference to a Supplier<String>, which is more semantically what you really need:
class TweetHandlerClass implements EventHandler<ActionEvent> {
private final Supplier<String> tweetSupplier ;
TweetHandlerClass(Supplier<String> tweetSupplier) {
this.tweetSupplier = tweetSupplier ;
}
#Override
public void handle(ActionEvent ae) {
System.out.println("Tweet button was clicked");
String newTweet = tweetSupplier.get();
}
}
and then
Button btTweet = new Button("Tweet");
TweetHandlerClass btTweetHandler = new TweetHandlerClass(tfPost::getText);
btTweet.setOnAction(btTweetHandler);
This is pretty much overkill though. Normally you would just define the event handler with a lambda expression, instead of an explicit class:
Button btTweet = new Button("Tweet");
btTweet.setOnAction(e -> {
System.out.println("Tweet button was clicked");
String newTweet = tfPost.getText();
// ..
});
Is it possible to limit the input length in a JavaFX HTMLEditor? I tried to add an event handler to the editor and consume the event when the content reaches a predefined limit but it doesn't seem to work.
editor.addEventHandler(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent arg0) {
if (editor.getHtmlText().length() >= MY_LIMIT) {
arg0.consume();
}
}
});
Did anybody manage to achieve this? Is it even possible?
Thanks in advance.
I'm sure there is a more elegant way to solve this problem, but the following code should work:
You need the two private class attributes
private static final int MAX_LENGTH = 250;
private String content;
and the following event handler
editor.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(editor.getHtmlText().length() <= MAX_LENGTH) {
content = editor.getHtmlText();
}
}
});
editor.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if(editor.getHtmlText().length() > MAX_LENGTH) {
editor.setHtmlText(content);
}
}
});
How to return result from event handler in javafx? I have bellow code, and how to return data from event to function showPrompt? Is it possible to recover the data for the function of the event?
public static String showPrompt(String title, String defValue){
final Stage dlgStage = new Stage();
TextField txtPromptValue = new TextField(defValue);
Button btnOk = new Button("Ok");
Button btnCancel = new Button("Cancel");
btnOk.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent arg0) {
//How to return data from event to function?
dlgStage.close();
}
});
btnCancel.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent arg0) {
//How to return data from event to function?
dlgStage.close();
}
});
//
Label lblTitle = new Label(title);
lblTitle.setFont(Font.font("Amble CN", FontWeight.NORMAL, 14));
//
VBox vbox = new VBox(lblTitle,txtPromptValue,btnOk,btnCancel);
vbox.setAlignment(Pos.CENTER);
vbox.setMinSize(300, 200);
//
Scene dlgScene = new Scene(vbox);
//
dlgStage.setScene(dlgScene);
dlgStage.initStyle(StageStyle.UNDECORATED);
dlgStage.initModality(Modality.APPLICATION_MODAL);
dlgStage.setMinWidth(300);
dlgStage.setMinHeight(200);
dlgStage.show();
}
The short answer is you can't return a value.
Why ?
This code bellow is called a callback.
new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent arg0) {
dlgStage.close();
}
}
Callbacks have no return type, as you can see in the example above, it is void.
Callbacks are methods that you pass as an argument to another method. The other method will call you callback method when it wants. This means that callbacks are asynchronous. In your example, it calls the callback when you press the button.
In conclusion, you can't return from it using return.
What to do ?
You can call a method from your callback and sent your return value to it as an argument.
Example:
btnCancel.setOnAction(
new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent arg0) {
YourClass.setReturnValue("This is button Cancel");
dlgStage.close();
}
}
});
Where setReturnValue is a method belonging to YourClass or an instance of it so it will retail your returned value.
Another way better approach would be to create a class that extends Stage maybe. Also in your showPrompt method you will have to block execution using showAndWait() or similar.
In conclusion, you can't create your entire Prompt from just one method.
You can't, because by the time you've opened and closed the prompt stage, the main thread will have already passed the showPrompt method.
As Andrei said, what you need to do is create your own custom PromptStage with a showPrompt API that blocks the main thread until the prompt stage is closed.
public static String showPrompt(final String title, final String defValue)
{
// This line will block the main thread
// See the "showAndWait()" API from JavaFX
final boolean result = PromptStage.showPrompt("My Prompt Stage", " ");
// And when the stage is closed, it will carry on to this piece of code
if (result)
{
return "This is button OK";
}
else
{
return "This is button CANCEL";
}
}
Or you could even create instances of your PromptDialog if you like
public static String showPrompt(final String title, final String defValue)
{
final PromptStage pStage = new PromptStage();
// This line will block the main thread
// See the "showAndWait()" API from JavaFX
pStage.showAndWait();
return pStage.getResultAsString();
}
There are very many approaches here. To be honest, I won't bother writing the whole class for you. However, do comment if you're stuck.
Another option is to pass the showPrompt(...) method a StringProperty, and update the property in your OK button's handler. The caller of showPrompt can then create the StringProperty, register a listener with it, and observe it. Something like:
public String showPrompt(String title, String defValue, final StringProperty result){
// ...
final TextField txtPromptValue = new TextField(defValue);
// ...
btnOk.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
result.set(txtPromptValue.getText());
dlgStage.close();
}
});
// ...
}
Then you call the dialog with something like:
StringProperty dialogResult = new SimpleStringProperty();
dialogResult.addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
// process newValue, the value from the dialog...
}
});
showPrompt("Dialog Title", "Default value", dialogResult);
I've a container which output markup placeholder tag is set to true. I want to display it only if I digit in a certain text field a certain string. For example if I digit "show" in text field, container appears, if I digit "hide" it disappears. I made this code:
container.setOutputPlaceHolderTag(true);
container.setOuputMarkupId(true);
textfield.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget target) {
form.modelChanged();
if ("SHOW".equals(textfield.getModelObject())) {
container.setVisible(true);
} else {
container.setVisible(false);
}
target.addComponent(container);
}
this code works only if I write SHOW, BUT when I write another string it doesn't disappear. To make it disappear I've to refresh the whole form they are into (and I don't want it).
How can I solve this problem??
some details: all component I'm refering to are in a form, and only if I refresh the form setVisible(false) works. From now only setVisible(true) works, it seems the container stucks on visibility true.
This code works:
public class HomePage extends WebPage {
private static final long serialVersionUID = 1L;
private String someValue;
private WebMarkupContainer container;
public HomePage(final PageParameters parameters) {
super(parameters);
add(container = container());
add(textfield());
}
private WebMarkupContainer container() {
WebMarkupContainer wmc = new WebMarkupContainer("container") {
#Override
protected void onConfigure() {
super.onConfigure();
setVisible("SHOW".equals(someValue));
}
};
wmc.setOutputMarkupPlaceholderTag(true);
return wmc;
}
private TextField textfield() {
TextField tf = new TextField("textfield", new PropertyModel(HomePage.this, "someValue"));
tf.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget art) {
//just model update
art.add(container);
}
});
return tf;
}
}
Use
container.setOutputPlaceHolderTag(true);
container.setOuputMarkupId(true);
textfield.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget target) {
form.modelChanged();
if ("SHOW".equals(((TextField<String>) getComponent()).getModelObject())) { //change this
container.setVisible(true);
} else {
container.setVisible(false);
}
target.addComponent(container);
}
I got this tip from Getting a Wicket text box's value in an AJAX onchange event
I have a Navigator class and a custom DialogBox class which is descended from GridPane.
public DialogBox(final JDialog jdialog) {
Label lblKeyName = new Label("Enter New Key");
Label lblKeyType = new Label("Select Key Type");
TextField txtKeyName = new TextField();
ComboBox cboKeyType = new ComboBox();
txtKeyName.getText();
Button btnOk = new Button("OK");
Button btnCancel = new Button("Cancel");
btnOk.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
//TODO: Somehow return the values in the ComboBox and TextField
}
});
btnCancel.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
jdialog.setVisible(false);
}
});
txtKeyName.prefWidth(300);
cboKeyType.prefWidth(300);
this.add(lblKeyName, 0, 0);
this.add(lblKeyType, 0, 1);
this.add(txtKeyName, 1, 0);
this.add(cboKeyType, 1, 1);
this.add(btnOk, 0, 2);
this.add(btnCancel, 1, 2);
}
This is the constructor for my DialogBox.
JFXPanel fxPanel = new JFXPanel();
testBox = new DialogBox(jdialog);
fxPanel.setScene(new Scene(testBox));
jdialog.add(fxPanel);
jdialog.setVisible(true);
How can I retrieve the values in the TextField and ComboBox? I can slightly recall a long ago class where the professor mentioned a technique involving the calling class (Navigator in this case) implementing an Interface and then passing itself to the DialogBox class to retrieve values. Unfortunately I have not found anything and cannot remember how it is done.
Assuming that the dialog is modal, basically, once btnOk or btnCancel button is pressed you need to change some kind of state flag which you can interrogate to determine how the dialog was closed...
// This will also handle the use case where the user presses the "x" button...
private boolean wasCancelled = true;
//...
public boolean wasCancelled() {
return wasCancelled;
}
In you action listeners, you need to set the state appropriately.
btnOk.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
wasCancelled = false;
jdialog.setVisible(false);
}
});
btnCancel.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
wasCancelled = true;
jdialog.setVisible(false);
}
});
Now, once the dialog returns, you need to check this flag...
jdialog.add(fxPanel);
jdialog.setVisible(true);
if (!jdialog.wasCancelled()) {
//...
}
You then need to supply "getter" methods to allow a caller to extract the values from the dialog...
public String getKey() {
return txtKeyName.getText();
}
public String getType() {
return cboKeyType.getSelectionModel().getValue();
}
This will mean you will need to create these two fields as instance variables