I am using a vaadin TextArea as a rough console. The user can enter commands which should be executed when he presses the enter key. Is there a way to specify this with a listener on the TextArea?
The closest thing I found is to use:
TextArea textArea = new TextArea();
textArea.addTextChangeListener(this);
textArea.setTextChangeEventMode(TextChangeEventMode.EAGER);
And handle the text change event:
#Override
public void textChange(TextChangeEvent event) {
System.out.println(event.getText());
}
This is however triggered as soon as text has been entered in the TextArea. I would like to be notified only when the enter key has been pressed.
You cannot listen to shortcut keys on the textarea itself, but a simple solution would be to add a submit button and use enter as it's shortcut:
Button b = new Button("submit", new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
// handle your event
}
});
layout.addComponent(b);
b.setClickShortcut(KeyCode.ENTER);
You can hide the button itself if you don't wish it:
b.setVisible(false);
Another solution would be to use ShortcutActions and Handlers as described in here:
https://vaadin.com/book/-/page/advanced.shortcuts.html
But in either case you have to take into account that listening to enter key will cause a conflict when using a TextArea component because you also need to use the same key to get to the next line in the TextArea.
You can add a ShortcutListener to the TextArea, like this:
TextArea textArea = new TextArea();
textArea.addShortcutListener(enter);
Now you just have to initialize some ShortcutListener as follows:
ShortcutListener enter = new ShortcutListener("Enter", KeyCode.ENTER, null) {
#Override
public void handleAction(Object sender, Object target) {
// Do nice stuff
log.info("Enter pressed");
}
};
For this, we use the following utility function
/**
* Perform the specified action when the text field has focus and `ENTER` is pressed.
*
* #param tf The {#link com.vaadin.ui.TextField text field} or
* {#link com.vaadin.ui.TextArea text area)
* #param action The action to perform
*/
public static void onKeyEnter(AbstractTextField tf, Consumer<AbstractTextField> action) {
tf.addFocusListener(event -> {
final Registration r = tf.addShortcutListener(
new ShortcutListener("Enter", KeyCode.ENTER, null) {
#Override
public void handleAction(Object sender, Object target) {
// sender: UI, target: TextField
assert target == tf;
action.accept(tf);
}
});
tf.addBlurListener(e -> r.remove());
});
}
To use it:
final TextField searchField = new TextField(); // or TextArea
searchField.setPlaceholder("Search text (ENTER)...");
// ..
onKeyEnter(searchField, tf -> doSearch(tf.getValue()));
//Refactored for vaadin 7
public static void onKeyEnter(AbstractTextField tf, Consumer<AbstractTextField> action) {
tf.addFocusListener(event -> {
ShortcutListener scl = new ShortcutListener("Enter", KeyCode.ENTER, null) {
public void handleAction(Object sender, Object target) {
assert target == tf;
action.accept(tf);
}
};
tf.addShortcutListener(scl);
tf.addBlurListener(e -> tf.removeShortcutListener(scl));
});
}
Related
I have a main window called MainFrame which is a jForm to which I update the data depending on a timer, but the problem is that I cannot update the data in the same MainFrame after using the jdialog, since I end up creating another duplicate window, but with the data changed, one with the original timer and the other with the new timer, I know that I can close the first window with dispose() and then keep the second, but I would like to avoid changing windows so much
the code with which I create another window when pressing the jDialog button is the following
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
// TODO add your handling code here:
String textoFieldTimer = jTextField1.getText();
int timeUserConfig = Integer.parseInt(textoFieldTimer);
Timer timeDefault = new Timer(timeUserConfig, null);
TokenAccess token = new TokenAccess();
token.access_code = code;
MainFrame mainFrame = new MainFrame(token);
mainFrame.setVisible(true);
mainFrame.timeDefault.stop();
mainFrame.timeDefault = timeDefault;
mainFrame.setUpdateTime(timeUserConfig);
this.dispose();
}//GEN-LAST:event_jButton1ActionPerformed
Is there any alternative to update the window? something like mainFrame.update(); or maybe send the value of the jTextField from the jDialog to mainFrame? since the previous code creates another MainFrame for me.
Method main setLabel and Timer.start/stop
public void setUpdateTime(int timeUserConfig) {
this.timeUserConfig = timeUserConfig;
if (timeUserConfig == 0) {
timeDefault.start();
timeDefault.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
setLabelText();
String timeUserConfigStr = Integer.toString(timeDefaultInt);
tiempoActualizado.setText("Tiempo de Actualizado: " + timeUserConfigStr+"ms");
}
});
} else {
timeDefault.stop();
timeDefault = new Timer(timeUserConfig, null);
timeDefault.start();
timeDefault.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
setLabelText();
String timeUserConfigStr = Integer.toString(timeUserConfig);
tiempoActualizado.setText("Tiempo de Actualizado: " + timeUserConfigStr+"ms");
}
});
}
}
setLabelText is a method set of label
public void setLabelText() {
String humedadStr = String.valueOf(humedad);
String temperaturaStr = String.valueOf(temperatura);
String presionStr = String.valueOf(co2);
temporalHum.setText(humedadStr);
temporalTemperatura.setText(temperaturaStr);
temporalPresion.setText(presionStr);
}
Any help would be appreciated.
Thanks for the update, and I found another solution without using an OptionPane from this question: programmatically close a JPanel which is displayed in JDialog.
I cannot replicate your codings
Start with the MainFrame, assuming you opened the JDialog by clicking on a button and wants to setText() to label lbSomething:
private void btInputActionPerformed(java.awt.event.ActionEvent evt) {
// Open new JDialog when button is clicked
NewJDialog dialog = new NewJDialog(new javax.swing.JFrame, true);
dialog.setVisible(true);
// Get user input from JDialog
String temp = dialog.getInput();
if (temp != null) {
/*
* Perform jButton1ActionPerformed() content here
* Including timeUserConfig, timeDefault and setUpdateTime() here
* so that you don't have to access mainFrame in the JDialog.
*/
lbSomething.setText(temp);
}
}
Then about the JDialog (with simple input detection):
public class NewJDialog extends javax.swing.JDialog {
// Set the variable as class variable
private String textTOFieldTimer;
public NewJDialog(java.awt.Frame parent, boolean modal) {
// default contents
}
#SupressWarinings("unchecked")
private void initComponents() {
// default contents
}
private void btSaveAction Performed(java.awt.event.ActionEvent evt) {
// Check if input correct and whether to disable JDialog
if (tfInput.getText.length() != 0) {
input = tfInput.getText();
// Connect to the whole JDialog by getWindowAncestor()
Window window = SwingUtilities.getWindowAncestor(NewJDialog.this);
// Just setVisible(false) instead of dispose()
window.setVisible(false);
} else {
JOptionPane.showMessageDialog(this, "Wrong Input");
}
}
public String getInput() {
return textToFieldTimer;
}
// default variables declarations
}
Hope this answer helps you well.
Would be better if you displayed the source code, but a simple solution to update values to an existing JFrame is by using setText() and getText().
For example:
String input = JOptionPane.showInputDialog(this, "Nuevo valor");
lbPresionActual.setText(input);
If you created a self-defined JDialog, it is about to transfer the input value when closing the JDialog, and that could be a different question.
I am writing a class (UIPromptComboBox) that extends JComboBox. The combobox is editable and for one application of the class it is implemented with a controlling ActionListener.
Currently, when the combobox is edited it fires the ActionListener which is good. However this ActionListener is also fired when I deselect the combobox and I cannot distinguish between the two events nor do I want it to fire when the combobox is deselected.
Implementing Class
private void addUIField() {
// Initialise and place combobox
this.myGuiTextField = new UIPromptComboBox();
myGuiTextField.setSize(COMBO_WIDTH, defaultHeight);
GuiUtils.positionControl(myPanel, myGuiTextField, myTop, PROMPT_X_LOC);
//Add action listener
myGuiTextField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("comboBoxEdited")) {
newUIcreated((UIPromptComboBox) evt.getSource());
}
}
private void newUIcreated(UIPromptComboBox alteredGuiTextField) {
try {
UIPrompt uip = alteredGuiTextField.getUIPrompt(((PowerPointTextItem) myPPTRef).getValue());
if (!simInfo.isInPrompts(uip)) {
simInfo.addUIPrompt(uip);
alteredGuiTextField.addNewUIPrompt(uip);
}
} catch (MissingPowerpointItem ex) {
Exceptions.printStackTrace(ex);
}
}
});
}
Class that extends JComboBox
public class UIPromptComboBox extends JComboBox {
public UIPromptComboBox(UIPrompt[] items) {
super(items);
this.setEditable(true);
}
public UIPromptComboBox() {
this.setEditable(true);
this.setEnabled(false);
}
/**
* returns either the selected UI prompt or a new prompt using the example
* text
*
* #param exampleText only used if new prompt is created
* #return UI prompt selected
*/
public UIPrompt getUIPrompt(String exampleText) {
UIPrompt uIPrompt = null;
Object returnedItem = this.getSelectedItem();
if (returnedItem instanceof UIPrompt) {
uIPrompt = (UIPrompt) returnedItem;
} else if (returnedItem instanceof String) {
uIPrompt = new UIPrompt((String) returnedItem, exampleText);
}
return uIPrompt;
}
public void addNewUIPrompt(UIPrompt newPrompt) {
ActionListener[] actionListerners = this.getActionListeners();
this.removeActionListener(this);
this.addItem(newPrompt);
this.setSelectedItem(newPrompt);
for (ActionListener al : actionListerners) {
this.addActionListener(al);
}
}
/**
* Used for displaying a report value sentence
* i.e. a string that is not associated with UI Prompts
* #param newText report value sentence
*/
public void setText(String newText) {
this.removeAllItems();
this.addItem(newText);
this.setSelectedItem(newText);
}
/**
* For when the UI prompts can be added on construction
*
* #param currentUIs list of UI promts
*/
public void addItems(UIPrompt[] currentUIs) {
this.removeAllItems();
DefaultComboBoxModel boxModel = new DefaultComboBoxModel(currentUIs);
this.setModel(boxModel);
}
}
The multiple firing due to losing focus is causing multiple objects to be created and added to the list. I think I may have implemented the ActionListener incorrectly. Thank you for your help
as you stated you only want the event to fire if the user presses enter. a better way to implement that, would be using an keylistener instead of an action listener.
myGuiTextField.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
newUIcreated((UIPromptComboBox) evt.getSource());
}
}
private void newUIcreated(UIPromptComboBox alteredGuiTextField) {
try {
UIPrompt uip = alteredGuiTextField.getUIPrompt(((PowerPointTextItem) myPPTRef).getValue());
if (!simInfo.isInPrompts(uip)) {
simInfo.addUIPrompt(uip);
alteredGuiTextField.addNewUIPrompt(uip);
}
} catch (MissingPowerpointItem ex) {
Exceptions.printStackTrace(ex);
}
}
});
this should now only fire your event newUIcreated, once the users presses enter and at no other time. replace your action listener with this
I have now finally found the issue.
The displaying of the UIPrompt included the addition of a string that sometimes contained a new line character.
The action of clicking another field was triggering the render of the UIPrompt however when this contained a newline character it was triggering the ActionListener again. This what the reason for the repeated action of comboBoxEdited.
This is my code
JToolBar customizeKeys = new JToolBar();
customizeKeys.add(new ChangeKeyListen("left"));
private class ChangeKeyListen extends AbstractAction{
private JDialog myDialog;
class KeyGetter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
OtherPanel.this.map(
KeyEvent.getKeyText(e.getKeyCode()),
keyAction);
myDialog.setVisible(false);
myDialog.removeKeyListener(getKeyListeners()[0]);
}
};
public ChangeKeyListen(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
myDialog = new JOptionPane().createDialog("Press a key");
myDialog.setVisible(true);
myDialog.requestFocusInWindow();
System.out.println(myDialog.getFocusableWindowState());
myDialog.addKeyListener(new KeyGetter());
System.out.println( myDialog.getKeyListeners());
}
}
What I am trying to do here is when the user clicks the JButton that was added to the JToolBar with the attributes of its action, the user will be prompted with my own customized dialog box. The user can then press any key to close the dialog box.(it actually just be invisible). When I run the application, everything looks fine. The JToolBar looks right and the button looks right. When I click the button, the correct controller behavior occurs as the dialog box is popped up.(just visible) However the key adapter's keyPressed method isn't being triggered at all when i press a key.
What I've done to debug this is to first make sure that the JDialog can first of all be focusable so it can receive key events from the keyboard. I did that with this line of
System.out.println(myDialog.getFocusableWindowState());
and what I got on the console was true. Next I made sure that the key listener was being set. I did that with
System.out.println( myDialog.getKeyListeners());
and this printed out
[Ljava.awt.event.KeyListener;#350b914b
which I assumed was a correct memory address for an object allocated from the heap.
I then checked out similar threads.
My issue couldn't be Jbutton listener isn't triggered, why? because the dialog box showed up and I made sure that the key listener was added with the print key listeners line.
I couldn't use what the user said in Trying to use key Listener because I need to listen for the key press and use that key press later in my program.
And this doesn't help either Why wont this KeyEvent work?
because I need a general reaction to key presses to obtain which key was pressed.
I know that keyPressed isn't being executed because I put a breakpoint inside the method and this print statement
System.out.println(KeyEvent.getKeyText(e.getKeyCode()));
wasn't printing anything on the console.
Does anyone know how i can fix this issue?
You are adding the KeyListener to the dialog created by the JOptionPane.
However, focus is on the JButton on the dialog. KeyEvents are only dispatched to the component with focus so your key listener code is never invoked.
Why are you trying to listen for any key to close the dialog? The is NOT user friendly. The user does not know that is the way to close the dialog since this is not a standard UI convention. The user should click on the button to close the dialog.
If you really do need to listen to any key pressed while the dialog is open then check out Global Event Listeners which shows how you can use an AWTEventListener to listen for any key event regardless of which component has focus.
Having dealt with very similar issues, I encourage people who want to add listeners to the components of their JDialog to follow the approach shown here. It allows for more control over the components.
The following example demonstrates a custom dialog that validates the user's input each time the text changes using a KeyListener.
public class DialogWithListener extends JDialog {
private JTextField textField = new JTextField();
private boolean userPressedOk = false;
/**
* Creates a dialog that lets the user enter text in a text field.
* <p>
* Each time the user presses a key, the text is validated using the
* {#link Predicate}s in {#code predsAndMsgs}. If the text doesn't satisfy
* all predicates, the dialog shows the message associated with the first
* unsatisfied predicate.
*
* #param predsAndMsgs
* a map from {#link Predicate}s to the messages we'll show to
* users if the text they entered doesn't satisfy the predicates
*/
public DialogWithListener(Map<Predicate<String>, String> predsAndMsgs) {
JLabel textFieldLabel = new JLabel("Enter text:");
// Show this if the text the user entered satisfies our predicates
String okText = "All good";
JLabel statusLabel = new JLabel(okText);
Object[] paneContent = { textFieldLabel, textField, statusLabel };
JButton okButton = new JButton("OK");
okButton.addActionListener(e -> {
userPressedOk = true;
setVisible(false);
});
Object[] options = { okButton };
JOptionPane optionPane = new JOptionPane(paneContent,
JOptionPane.QUESTION_MESSAGE, JOptionPane.DEFAULT_OPTION, null,
options);
getContentPane().add(optionPane);
setLocationRelativeTo(optionPane.getParent());
setFocusTo(textField);
// Check the user input each time a key is released
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent event) {
validate(predsAndMsgs, textField.getText(), okText,
statusLabel, okButton);
}
});
setModal(true);
setResizable(false);
pack();
}
/**
* Validates the {#code textToValidate}.
* <p>
* The {#link Predicate}s in {#link predsAndMsgs} determine whether the text
* is valid. If the text is invalid, we show the message that is associated
* with the predicate and disable this dialog's OK button.
*
* #param predsAndMsgs
* a map from {#link Predicate}s that must hold for the
* {#code textToValidate} to the messages we'll show to the user
* if a predicate is not satisfied.
* #param textToValidate
* we validate this text against the {#link Predicate}s in
* {#link predsAndMsgs}
* #param okText
* this text is shown if the {#code textToValidate} satisfies all
* predicates
* #param statusLabel
* a {#link JLabel} that either shows the {#link okText} or the
* message of the first predicate that doesn't hold true for the
* {#link textToValidate}
* #param okButton
* we enable and disable this button depending on whether the
* {#link textToValidate} is valid
*/
private void validate(Map<Predicate<String>, String> predsAndMsgs,
String textToValidate, String okText, JLabel statusLabel,
JButton okButton) {
// Get the first predicate that the text to validate doesn't satisfy
Optional<Predicate<String>> unsatisfiedPredMaybe = predsAndMsgs
.keySet().stream().filter(pred -> !pred.test(textToValidate))
.findFirst();
// At least one predicate was not satisfied
if (unsatisfiedPredMaybe.isPresent()) {
// Tell the user the text they entered can't be accepted
String msg = predsAndMsgs.get(unsatisfiedPredMaybe.get());
statusLabel.setText(msg);
okButton.setEnabled(false);
} else {
statusLabel.setText(okText);
okButton.setEnabled(true);
}
pack();
}
private void setFocusTo(JComponent comp) {
addComponentListener(new ComponentAdapter() {
#Override
public void componentShown(ComponentEvent ce) {
comp.requestFocusInWindow();
}
});
}
public Optional<String> display() {
userPressedOk = false;
// Because the dialog is modal it will block here
setVisible(true);
String dialogResult = null;
if (userPressedOk) {
dialogResult = textField.getText();
}
return Optional.ofNullable(dialogResult);
}
}
And this is how you create and show the dialog:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException
| UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
JFrame frame = new JFrame();
JButton showDialogButton = new JButton("Show Dialog");
// Define the predicates that the user entered-text should satisfy and
// the messages shown to the user if it doesn't
Map<Predicate<String>, String> predicatesAndMessages = new HashMap<>();
Predicate<String> dontMentionHisName = text -> !text
.contains("Voldemort");
predicatesAndMessages.put(dontMentionHisName,
"Sssh! You can't say that!");
DialogWithListener dialog = new DialogWithListener(
predicatesAndMessages);
dialog.setTitle("My dialog");
showDialogButton.addActionListener(e -> dialog.display().ifPresent(
userText -> System.out.println(userText)));
frame.getContentPane().add(showDialogButton);
frame.pack();
frame.setVisible(true);
}
So I've stolen this cool PopupComposite, and I am really satisfied with it.
There's just one issue. If it put a org.eclipse.swt.widgets.Text in it, I open the popup, focus the Text, and press ESC, then both the Text and the PopupComposite dispose themselves.
I really can't figure out where the dispose call is coming from. Is it a Shell issue? What Shell should I use with the popup?
SSCCE:
/**
*
* #author ggrec
*
*/
public class PopupCompositeTester
{
public static void main(final String[] args)
{
new PopupCompositeTester();
}
private PopupCompositeTester()
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
createContents(shell);
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if ( !display.readAndDispatch() )
display.sleep();
}
display.dispose();
}
private static void createContents(final Composite parent)
{
final Button button = new Button(parent, SWT.PUSH);
button.setText("Poke Me");
final PopupComposite popup = new PopupComposite(parent.getShell());
new Text(popup, SWT.NONE);
popup.pack();
button.addSelectionListener(new SelectionAdapter()
{
#Override public void widgetSelected(final SelectionEvent e)
{
popup.show( Display.getDefault().map(parent, null, button.getLocation()) );
}
});
}
}
The reason for this is because when you focus the text field and press Escape, the field sends a SWT.TRAVERSE_ESCAPE event to its parent shell. The shell (in your case not being a top-level shell) responds by calling Shell.close(). You can work around that by adding a traverse listener to your text field, which would cancel the event (code below).
new Text(popup, SWT.NONE).addTraverseListener(new TraverseListener() {
#Override
public void keyTraversed(TraverseEvent e) {
if(e.detail == SWT.TRAVERSE_ESCAPE) {
e.doit = false;
}
}
});
Keep in mind, this is a rather crude solution to your specific issue. I would not recommend using this for anything other than testing purposes. You can read more about this here -> http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fswt%2Fevents%2FTraverseEvent.html
And here: http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fswt%2Fwidgets%2FShell.html
Because my "bug" is actually a normal behaviour of the SWT platform, I've used the following workaround:
/**
* Lazy initialization of the popup composite
*/
private void createPopup()
{
// popupContainer is now a field
if (popupContainer != null && !popupContainer.isDisposed())
return;
// ... create popup AND its contents ...
}
and in the button listener:
createPopup();
popup.show( Display.getDefault().map(parent, null, button.getLocation()) );
Thank you #blgt
There's a text field and when lost focus it will validate the inputs, if not passed, print out the error message (to be simple here just has an empty check). And there's a button next to the text field, it will print out the text once click on it.
As I tried, when input some text and then click the button it will trigger both the focus lost event of text field and the event of button. In a other word, it will do the validation first and then print out the input text.
Here comes my question, what is the good approach to prevent printing out the text if the validation not passed? Or is there a way to "ignore" the click event on button if validation not passed?
I tried to use a boolean flag which indicate the validation result and check the flag when perform the action for button, but I do not think it is a good approach. As I know there's an event dispatcher thread in Swing which deal with the events, is it possible I can cancel the events from here?
Below is a piece of code which explain the question:
public class SimpleDemo
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = new JPanel(new FlowLayout());
frame.setContentPane(content);
final JTextField textField = new JTextField(10);
textField.addFocusListener(new FocusAdapter()
{
#Override
public void focusLost(FocusEvent e)
{
String text = textField.getText();
// do some validation here, if not validated
// do not trigger the event on button.
if ("".equals(text))
{
System.out.print("please input a text!");
}
}
});
content.add(textField);
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
// action performed for button
String text = textField.getText();
System.out.println(text);
}
});
content.add(button);
frame.setVisible(true);
frame.pack();
}
}
I faces similar issue while working on an application. I solved it like below
I created a abstract class ApplicationFrame which every frame in the application extends
public abstract class ApplicationFrame extends JFrame implements ActionListener {
#Override
final public void actionPerformed(ActionEvent event) {
if(validateInput()){
performAction(event);
}
}
/*
* Sub class should override this method to receive any action
*/
protected void performAction(ActionEvent event) {};
/*
* Sub class should override this method to perform validation
*/
abstract protected boolean validateInput();
}
All Frames will now extend this base frame, as below:
public class Frame1 extends ApplicationFrame{
#Override
protected void performAction(ActionEvent event) {
// perform action
}
#Override
protected boolean validateInput() {
// return true or false depending upon the validation results
}
// if you want to add Action Listener, you need to add like this:
btnSomeButton.addActionListener(this);
}
If you need to handle Focus events, you can make ApplicationFrame or the base frame implement FocusListener.
This is my custom implementation to solve the problem, hope this helps.
Make the button disabled on start-up
Upon lost focus, validate the text & enable button only when the input passes validation.
Upon start of text change, disable the button
It's always makes sense to make ui to communicate with user. So you can show "please input a text" as the default text of the textField when nothing is entered by user.
Here is the code for such custom textField:
public class TextFieldWithDefaultText extends JTextField implements FocusListener{
private final String hint;
public TextFieldWithDefaultText (String $text)
{
super($text);
this.hint = $text;
addFocusListener(this);
}
#Override
public void focusGained (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText("");
}
}
#Override
public void focusLost (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText(hint);
}
}
#Override
public String getText ()
{
String typed = super.getText();
return typed.equals(hint) ? "" : typed;
}
}
Write the acttionListerner for your button like this:
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(!textField.getText().isEmpty())
System.out.println(textField.getText());
}
});
And ur textField implementation should be :
final TextFieldWithDefaultText textField = new TextFieldWithDefaultText ("please input a text");
Hope this helps :)