Clicking the textfield and clear the text? - java

Is it possible that when I clicked the textfield it would clear the recent text that was inputed there?. Mine was like, suppose these are textfields.
Name: Last Name First Name Middle Initial
Then I would click the Last Name and it would be cleared, same as First Name and Middle Initial. thanks for reading, hope you can help me.

Consider a FocusListener, one where all the text is selected:
myTextField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent fEvt) {
JTextField tField = (JTextField)fEvt.getSource();
tField.selectAll();
}
});
By selecting all of the text, you give the user the option of either typing and thus deleting the current text and replacing it with the new text, or using the mouse or arrow keys to keep the current text and possibly change it.

I think Hovercraft is right. Better to use a FocusListener for this purpose.
I would write a utility class that could deal with this, I've done something similar for auto select. Means I don't have to extend every text component that comes along or mess around with lost of small focus listeners that do the same thing.
public class AutoClearOnFocusManager extends FocusAdapter {
private static final AutoClearOnFocusManager SHARED_INSTANCE = new AutoClearOnFocusManager();
private AutoClearOnFocusManager() {
}
public static AutoClearOnFocusManager getInstance() {
return SHARED_INSTANCE;
}
#Override
public void focusGained(FocusEvent e) {
Component component = e.getComponent();
if (component instanceof JTextComponent) {
((JTextComponent)component).setText(null);
}
}
public static void install(JTextComponent comp) {
comp.addFocusListener(getInstance());
}
public static void uninstall(JTextComponent comp) {
comp.removeFocusListener(getInstance());
}
}
Then you just need to use
JTextField textField = new JTextField("Some text");
AutoClearOnFocusManager.install(textField);
If you're just looking to supply a "prompt" (text inside the field that prompts the user), you could also look at the Prompt API

Why don't use the mouseClicked event?
So, you can have something like
jTextFieldMyText.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jTextFieldMyTextMouseClicked(evt);
}
});
private void jTextFieldMyTextMouseClicked(java.awt.event.MouseEvent evt) {
jTextFieldMyText.setText("");
}
In the case of focus
jTextFieldMyText.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
jTextFieldMyTextFocusGained(evt);
}
});
private void jTextFieldMyTextFocusGained(java.awt.event.MouseEvent evt) {
jTextFieldMyText.setText("");
}
If deleting text inmediatelly isn't what's wanted, use selectAll() instead of setText("") as suggested many times

Related

Higlight text in JTextField but only when tabbing

I want to create a JDialog where the text in the textfields is selected but only if the focus is gained from keyboard (TAB, CTRL+TAB). I have found several topics on this matter but had problems with implementing it.
Here is one which I was trying.
And my code:
public class Dialogg extends JDialog implements FocusListener, MouseListener {
private boolean focusFromMouse = false;
public Dialogg() {
JTextField tf1 = new JTextField("text1");
JTextField tf2 = new JTextField("text2");
tf1.addMouseListener(this);
tf2.addMouseListener(this);
tf1.addFocusListener(this);
tf2.addFocusListener(this);
}
#Override
public void focusGained(FocusEvent e) {
if (!focusFromMouse) {
JTextField tf = (JTextField) e.getComponent();
tf.selectAll();
focusFromMouse = true;
}
}
#Override
public void focusLost(FocusEvent e) {
focusFromMouse = false;
}
#Override
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
}
It does not work as intended, it does not matter what is focus source the text always highlights. When I run the code and follow it step by step it turns out that focusGained code happens before mouseClicked code so the flag is not reset when it should. Any hints?
EDIT:
As suggested by M. Prokhorov I have deleted less relevant (for the question) lines from the code.Thank you.
EDIT 2:
I am trying to wrap focus listener as suggested by camickr. It looks like this now:
tf1.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent evt){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (!focusFromMouse){
tf1.selectAll();
focusFromMouse=true;
}
}
});
}
public void focusLost(FocusEvent evt){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
focusFromMouse=false;
}
});
}
});
public void mouseClicked(MouseEvent e) {
focusFromMouse=true;
I am printing line after each event to see the action order and still mouseClicked happens last. What am I doing wrong?
EDIT 3:
OK, I have found a solution which fulfils requirements of my simple Dialog.
I could not find a way of doing this with use of invokeLater or EventQueue. Vladislav's method works but as I understand it restricts the user to only use the keyboard.
I have used the initial approach but I have added an auxiliary variable and few conditions which allow to pass the flag "unharmed" trough Events that should not change the flag at given moment. It may not be subtle or universal but works for my app. Here is the code:
public void focusGained(FocusEvent e) {
if(!focusFromMouse){
if (higlight){
JTextField tf = (JTextField) e.getComponent();
tf.selectAll();
focusFromMouse=false;
}
}
}
public void focusLost(FocusEvent e) {
if (focusFromMouse){
higlight=false;
focusFromMouse=false;
}else{
higlight=true;
}
}
public void mousePressed(MouseEvent e) {
focusFromMouse=true;
}
At the first, by default, focus on JTextField is requested by mouse-press event, not by mouse-click.
So, this method:
public void mouseClicked(MouseEvent e) {
focusFromMouse = true;
}
is useless because the mouse-click event is triggered after the mouse-press event.
One way to solve your problem is to remove all native MouseListeners from JTextField:
...
for( MouseListener ml : tf1.getMouseListeners() ){
tf1.removeMouseListener(ml);
}
for( MouseMotionListener mml : tf1.getMouseMotionListeners() ){
tf1.removeMouseMotionListener(mml);
}
...
Another way is to handle all mouse events and consume those of them, which are triggered by JTextField:
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if( event.getSource() == tf1 ){
((MouseEvent)event).consume();
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
When I run the code and follow it step by step it turns out that focusGained code happens before mouseClicked
Wrap the code in the FocusListener in a SwingUtilities.invokeLater(). The will place the code on the end of the Event Dispatch Thread (EDT), so the code will run after the variable in the MouseListener has been set.
See Concurrency in Swing for more information about the EDT.
Edit:
Just noticed the other answer. You might be able to do something simpler. Istead of listener for mouseClicked, listen for mousePressed. A mouseClicked event is only generated AFTER the mouseReleased event, so by that time the FocusListener logic has already been executed, even when added to the end of the EDT.
Edit 2:
If the above doesn't work then you might be able to use the EventQueue.peek() method to see if a MouseEvent is on the queue. This might even be easier than worrying about using the invokeLater.

show character count in swing gui

I have a JTextArea called taMessage which displays a message string. This string can be edited by the user at run time.
I have a JLabel lblLength to show the number of characters. I am using lblLength.setText(taMessage.getText().length()+"/ 160"); to display the character count.
What event listener should I use for taMessage so that as I keep typing text in my text area, lblLength keeps on updating itself?
Something like we see in sites like way2sms or 160by2, where it shows the number of characters left.
Swing text fields and text areas are backed by a class called Document that can have a Document Listener attached to it.
The official docs have a decent tutorial on Document Listeners.
You would want to attach the document listener, and since you're interested in character counts then you'd simply want to use the same code you used above to initialize the label in all three of the Document Listener's callback methods.
In an MVC like way you can listen to the document's change.
JTextArea ta = ...;
JLabel lblLength = ...;
Document taDoc = ta.getDocument();
taDoc.addDocumentListener(new CharacterCounterDocumentListener(lblLength))
public class CharacterCounterDocumentListener implements DocumentListener {
private JLabel counterLabel;
public CharacterCounterDocumentListener(JLabel counterLabel){
this.counterLabel = counterLabel;
}
public void changedUpdate(DocumentEvent e) {
Document d = e.getDocument();
int length = d.getLength();
counterLabel.setText(Integer.toString(length));
}
public void insertUpdate(DocumentEvent e) {
}
public void removeUpdate(DocumentEvent e) {
}
}
A DocumentListener is probably your best bet. You don't even need to create a new class, you can just define it inline.
// Listen for changes in the text
taMessage.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
update();
}
public void removeUpdate(DocumentEvent e) {
update();
}
public void insertUpdate(DocumentEvent e) {
update();
}
public void update() {
lblLength.setText(taMessage.getText().length()+"/ 160");
}
});

Make text in JButton not visible

I made a button and did a .setText() on it because I have to compare the value of the .setText() with something else.
I applied the .setText() to a JButton, but I don't want the text to be visible in my button.
If I do setVisible(false) then it hides the whole button, but I only want it to hide the text.
Is there an option for this? I've considered making a custom font and apply it on the text in the .setText() but I'm wondering if there's a more efficient option to my problem.
Thanks in advance guys.
EDIT: I can't use .setText(" ") because I have to compare the value within it.
You state:
EDIT: I can't use .setText(" ") because I have to compare the value within it.
Nonsense. As I've mentioned in a comment, set the JButton's text to " ", and don't use the JButton's text for comparison. Instead use its actionCommand easily obtained via getActionCommand(). Or use a HashMap<JButton, SomethingElse>.
You may consider changing the JButton's Action when you need to change its behavior and state which is easily done by calling setAction(...)
For example,
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ButtonActions {
private static void createAndShowGui() {
JPanel mainPanel = new JPanel();
JButton myButton = new JButton();
StartAction startAction = new StartAction();
PauseAction pauseAction = new PauseAction();
BlankAction blankAction = new BlankAction();
startAction.setNextAction(pauseAction);
pauseAction.setNextAction(blankAction);
blankAction.setNextAction(startAction);
myButton.setAction(startAction);
mainPanel.add(myButton);
JFrame frame = new JFrame("ButtonActions");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class SwappingAction extends AbstractAction {
private Action nextAction;
public SwappingAction(String text) {
super(text);
}
public void setNextAction(Action nextAction) {
this.nextAction = nextAction;
}
public Action getNextAction() {
return nextAction;
}
#Override
/**
* super method needs to be called in child for swap to work
*/
public void actionPerformed(ActionEvent e) {
System.out.println("ActionCommand: " + e.getActionCommand());
((AbstractButton)e.getSource()).setAction(nextAction);
}
}
class StartAction extends SwappingAction {
public static final String START = "Start";
public StartAction() {
super(START);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
// start-specific code goes here
}
}
class PauseAction extends SwappingAction {
public static final String PAUSE = "Pause";
public PauseAction() {
super(PAUSE);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
// pause-specific code goes here
}
}
class BlankAction extends SwappingAction {
public static final String BLANK = " ";
public BlankAction() {
super(BLANK);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
}
}
Write buttonName.setText(" ") this will not display any name to the button. And whenever you feel like displaying the name (on any event) then set it again buttonName.setText("some text")
If you insist not to use setText(""), try setting same colour as a background colour and text colour. Check the below links
setBackground(java.awt.Color)
setForeground(java.awt.Color)
Why don't you name the first button " " (1 space).
the second: " " (2 spaces)
the third: " "(3 spaces) and so on ..
Now, compare:
if((event.getActionCommand()).equals(" "))
{ //1st button }
if((event.getActionCommand()).equals(" "))
{ //2nd button }
..and so on
where event is an object of ActionEvent
This way the buttons will have a unique names and be invisible.
Horrible coding, I know. But it does the trick ;)
Instead of .setText(), use .setTag() and .getTag() to attach some value to a View - including a Button - for later retrieval.
These methods are there directly for that kind of purpose.

In GWT is there a way to create a KeyPressEvent for the entire view instead of a single input element?

Right now I have the following code working:
#UiHandler("usernameTextBox")
void onUsernameTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
#UiHandler("passwordTextBox")
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
void keyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}
I would like the ability to have just one listener for all elements on the view without duplicating an event for each textbox.
The end goal is that if they press enter, regardless of where they are on the page, it should submit the form.
Thanks!
What works, but still requires you to specify it for each widget, but doesn't require duplicate code:
#UiHandler({"usernameTextBox", "passwordTextBox"})
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
Yes jackcrews is correct. Also you can try the following. It may be VerticalPanel, DockLayoutPanel etc....
UiBinder.ui.xml
<gwt:VerticalPanel ui:field="mainPanel">
<gwt:Label>Name</gwt:TextBox>
<gwt:TextBox ui:field="textBox">
</gwt:VerticalPanel>
Main.java
#UiField
VerticalPanel mainPanel;
public Main() {
focushandler();
}
void focusHandler() {
mainPanel.addDomHandler(new Handler(), KeyPressEvent.getType());
}
final class Handler implements KeyPressHandler {
#Override
public void onKeyPress(KeyPressEvent event) {
//Code what you expect
}
}
Actually this has more number of lines. But it is good practice.
Regards,
Gnik
I found out that the g:FocusPanel allows me to capture events for everything inside the panel.
#UiHandler("focusPanel")
void onFocusPanelKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}

Java Swing: Focus issue

I'm making a level editor for my game. I have a property panel where I can modify the selected object its properties. I also have a Save button to write the level xml.
A field-edit is submitted(*) when the editor component lost the focus or Enter is pressed. This is working great, but the only problem is that when I have this sequence of actions:
Edit a field
Press the save button
Because, what happens is this:
I edit the field
I press the save button
The level is saved
The field lost the focus
The edit is submitted
As you can see, this is the wrong order. Of course I want the field to lose its focus, which causes the submit and then save the level.
Is there a trick, hack or workaround to make the field first lose the focus and then perform the action listener of the save button?
Thanks in advance.
(* submit = the edit to the field is also made in the object property)
EDIT: For the field I'm using a FocusAdapter with focusLost:
FocusAdapter focusAdapter = new FocusAdapter()
{
#Override
public void focusLost(FocusEvent e)
{
compProperties.setProperty(i, getColor());
record(); // For undo-redo mechanism
}
};
And for the button a simple ActionListener with actionPerformed`.
btnSave.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
// Save the level
}
});
Hmm ... can't reproduce: in the snippet below the lost is always notified before the actionPerfomed, independent on whether I click the button or use the mnemonic:
final JTextField field = new JTextField("some text to change");
FocusAdapter focus = new FocusAdapter() {
#Override
public void focusLost(FocusEvent e) {
LOG.info("lost: " + field.getText());
}
};
field.addFocusListener(focus);
Action save = new AbstractAction("save") {
#Override
public void actionPerformed(ActionEvent e) {
LOG.info("save: " + field.getText());
}
};
save.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
JButton button = new JButton(save);
JComponent box = Box.createHorizontalBox();
box.add(field);
box.add(button);
On the other hand, focus is a tricky property to rely on, the ordering might be system-dependent (mine is win vista). Check how the snippet behave on yours.
If you see the same sequence as I do, the problem is somewhere else
if you get the save before the lost, try to wrap the the save action into invokeLater (which puts it at the end of the EventQueue, so it's executed after all pending events)
Action save = new AbstractAction("save") {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
LOG.info("save: " + field.getText());
}
});
}
};
Normally, wrapping your save code into an SwingUtilities.invokeLater() should do the trick. As you already mentioned, this doesn't work? Try this:
private boolean editFocus = false;
FocusAdapter focusAdapter = new FocusAdapter()
{
#Override
public void focusGained(FocusEvent e){
editFocus = true;
}
#Override
public void focusLost(FocusEvent e){
compProperties.setProperty(i, getColor());
record(); // For undo-redo mechanism
editFocus = false;
if (saveRequested){
save();
}
}
};
and for your button:
private boolean saveRequested = false;
btnSave.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (editFocus){
saveRequested = true;
return;
} else {
save();
}
}
});
and then your save method:
private void save(){
// do your saving work
saveRequested = false;
}
This only works when your focusLost gets called after your button's action. If suddenly the order is correct, this code will get save() called twice.
But again, wrapping your save() code in your original approach should work, because the save code will execute after processing all events. That is after processing your button click and your focusLost events. Because your focusLost code executes immediately (it's not wrapped in an invokeLater()), the focusLost code should be executed always before your save code. This does not mean that the event order will be correct! But the code associated to the events will executed in the right order.

Categories

Resources