3

i have jTextfield and jButton..

how to

  • user can click on jTextfield(mouse can enter/exited on jtextfield), but if user typing something it will not do anything (except backspace that will remove entire text)
  • when user click the button, it will

jTextfield.setText("something");

so the only way to give jtextfield text is click the button

  • when there are a text in there (when cursor inside jtextfield) then user typing a backspace, it will remove entire text on jtextfield..

how to do this?

forgive my english.. thanks a lot for any kind of help..

mopr mopr
  • 193
  • 2
  • 4
  • 13

2 Answers2

5

Use a DocumentFilter, simply add it to your JTextField like so:

 public class Test {

    public void initComponents() {

        //create frame

        //add DoucmentFilter to JTextField
        MyDocumentFilter myFilter = new MyDocumentFilter();
        JTextField myArea = new JTextField();
        ((AbstractDocument)myArea.getDocument()).setDocumentFilter(myFilter);

         //add components set frame visible
    }

 }

class MyDocumentFilter extends DocumentFilter {

    @Override
    public void replace(FilterBypass fb, int i, int i1, String string, AttributeSet as) throws BadLocationException {
        super.replace(fb, i, i1, string, as);
    }

    @Override
    public void remove(FilterBypass fb, int i, int i1) throws BadLocationException {
        super.remove(fb, i, i1);
    }

    @Override
    public void insertString(FilterBypass fb, int i, String string, AttributeSet as) throws BadLocationException {
        super.insertString(fb, i, string, as);
    }

}

alternatively

You may want to create a custom JTextField which already has a DocumentFilter (for re-usability) something like:

public class MyCustomField extends JTextField {

    public MyCustomField(int cols) {
        super(cols);
    }

    protected Document createDefaultModel() {
        return ((Document) new MyDocument());
    }

    static class MyDocument extends DocumentFilter {

        @Override
        public void insertString(FilterBypass fb, int i, String string, AttributeSet as) throws BadLocationException {
            super.insertString(fb, i, string, as);
        }

        @Override
        public void remove(FilterBypass fb, int i, int i1) throws BadLocationException {
            super.remove(fb, i, i1);
        }

        @Override
        public void replace(FilterBypass fb, int i, int i1, String string, AttributeSet as) throws BadLocationException {
            super.replace(fb, i, i1, string, as);
        }
    }
}

Edit from Hovercraft
I was thinking more along these lines

import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.text.*;

public class Test {

   public void initComponents() {

      JPanel panel = new JPanel();
      final MyDocumentFilter myFilter = new MyDocumentFilter();
      final JTextField myArea = new JTextField(20);
      ((AbstractDocument) myArea.getDocument()).setDocumentFilter(myFilter);

      panel.add(myArea);

      panel.add(new JButton(new AbstractAction("Set Text") {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            myFilter.setFiltering(false);
            myArea.setText("Fe Fi Fo Fum");
            myFilter.setFiltering(true);
         }
      }));

      JOptionPane.showMessageDialog(null, panel);

      // add components set frame visible
   }

   public static void main(String[] args) {
      new Test().initComponents();
   }

}

class MyDocumentFilter extends DocumentFilter {
   private boolean filtering = true;

   @Override
   public void replace(FilterBypass fb, int i, int i1, String string,
         AttributeSet as) throws BadLocationException {
      if (!filtering) {
         super.replace(fb, i, i1, string, as);
      }
   }

   @Override
   public void remove(FilterBypass fb, int i, int i1)
         throws BadLocationException {
      int offset = 0;
      int length = fb.getDocument().getLength();
      super.remove(fb, offset, length);
   }

   @Override
   public void insertString(FilterBypass fb, int i, String string,
         AttributeSet as) throws BadLocationException {
      if (!filtering) {
         super.insertString(fb, i, string, as);         
      }
   }

   public void setFiltering(boolean filtering) {
      this.filtering = filtering;
   }

}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • 4
    You should consider using `DocumentFilter` instead of `DocumentListener`. – Eng.Fouad Nov 22 '12 at 17:02
  • @Eng.Fouad +1 thank you will take a look, any advantages of the top of your head? – David Kroukamp Nov 22 '12 at 17:06
  • 2
    The advantage of a DocumentFilter is that its actions occur before the Document is altered which is why it can filter. But I don't see your filter currently doing any filtering. – Hovercraft Full Of Eels Nov 22 '12 at 17:26
  • thanks.. it will help.. but apologize i confuse how to handle the backspace problem with this (to complex for me T-T) – mopr mopr Nov 22 '12 at 17:33
  • 1
    @moprmopr no such thing as too complex more like too lazy... And in my example there is no concern of keys pressed, rather actions performed on the `JTextField` like when text is inserted, removed or added/updated. Using a `KeyListener` means code may be pasted into textfield without you knowing – David Kroukamp Nov 22 '12 at 17:35
  • 3
    No need to extend `JTextField`. You can introduce a utility method / factory method if you need to create textfields with the same filtering functionality in multiple places. – Robin Nov 22 '12 at 17:38
  • @Robin +1 true but I just took it from oracle docs on `JTextField`, there was an example, which is what I used as foundation – David Kroukamp Nov 22 '12 at 17:39
  • 2
    Please see my edit to your answer regarding turning filtering on and off, and allowing deletion of the entire text. Sorry to edit your answer, and please feel free to delete my edit as you wish. – Hovercraft Full Of Eels Nov 22 '12 at 17:48
  • @HovercraftFullOfEels +1. And no need to be sorry when you just helped increase my post quality. Thank you and great edit/example ;) I would +1 the answer if it wasn't mine – David Kroukamp Nov 22 '12 at 17:50
  • 1
    thanks a lot.. its the best answer in my case... sory for long response my minds loading very slowly.. @DavidKroukamp hehe i not lazy to much.. i just don't know what i must do in documentlistener/document filter(i know how to use it, but i don't know what to do) till hovercraft edit it.. thanks ^^ – mopr mopr Nov 22 '12 at 18:33
3

in the key listener of the jTextfield, in the keyTyped event, check the e.getKeyChar() if it is the backspace, if not, do e.consume(); it will cancel the event

the keychar for backspace is 8

here is an example:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;


public class ConsumeExceptForBackSpace extends JFrame {

    private boolean canWrite = false;

    public ConsumeExceptForBackSpace() {
        super();

        JButton b = new JButton("Click");
        JTextField f = new JTextField("");
        this.setLayout(new BorderLayout());
        this.add(b, BorderLayout.CENTER);
        this.add(f, BorderLayout.SOUTH);

        b.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                canWrite = !canWrite;
            }
        });

        f.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
                if(e.getKeyChar() != KekEvent.VK_BACK_SPACE && !canWrite) e.consume();
            }

            @Override
            public void keyReleased(KeyEvent e) {

            }

            @Override
            public void keyPressed(KeyEvent e) {

            }
        });

        this.pack();
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new ConsumeExceptForBackSpace();
    }
}
doctor killer
  • 392
  • 1
  • 14
  • 3
    I do not think a `KeyListener` should be used with Swing components as its AWT. There are many newer Swing options like: `KeyBindings`, `DocumentFilter` and `DocumentListener` etc. Also Swing components should always be created and manipulated on [EDT](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) – David Kroukamp Nov 22 '12 at 17:06
  • 1
    @moprmopr you should not like bad coding, There is a `KeyEvent` class just for this: [`KeyEvent.VK_BACK_SPACE`](http://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyEvent.html#VK_BACK_SPACE) not 8, thats really un-readable!. -1 to doctorKiller – David Kroukamp Nov 22 '12 at 17:34
  • 2
    @moprmopr: you are making a mistake in accepting this answer as you really don't want to use a KeyListener for this, and there is a risk that this will cause problems later if modifications are made to your code, especially if another component needs focus. – Hovercraft Full Of Eels Nov 22 '12 at 17:38
  • 1
    @HovercraftFullOfEels +1 and not forgetting with `KeyListener` code may be copied and pasted into `JTextField` without notification – David Kroukamp Nov 22 '12 at 17:41
  • 1
    @David Kroukamp instead of -1 because i iser 8 instead of VK_BACK_SPACE, just edit the answer...this is why stackoverflow exists... – doctor killer Nov 22 '12 at 18:06
  • @doctorkiller if I found the example good I would have but its going against all swing practices , which added to the reason i downvoted – David Kroukamp Nov 22 '12 at 18:25
  • of course this is one of the correct answer but there just another more complete answer.. ~,~ – mopr mopr Nov 22 '12 at 18:32
  • 1
    I would agree that it's not a preferred answer -- better to use filter or key bindings (in my opinion), but it's not terrible bad either. 1+ – Hovercraft Full Of Eels Nov 22 '12 at 18:42
  • @David Kroukamp It is still interesting: through all of my java experience, I have never taught something else than these listeners existed: all tutorials show swt listeners on Swing components...so this is what I learned: I will take a look at the swing solution as you are correct to say that the most modern coding practice is the way to go. – doctor killer Nov 22 '12 at 18:53
  • @doctorkiller lifted my down vote... Guess it was unnecessary as it does solve the problem (maybe not as efficiently) but lets not nit pick :P – David Kroukamp Nov 22 '12 at 20:02
  • @DavidKroukamp you got mine as I do agree with your principle of getting rid of the AWT from the swing – doctor killer Nov 22 '12 at 20:31