0

I am trying to extract card number from a USB swipe card reader. The code I put together works for 1 swipe and the GUI freezes. If the Thread sleep bits are commented-out the GUI does not freezes but I get 0 at output. Any suggestion on what I am doing worng will be helpful. Here is the code

userText.getDocument().addDocumentListener(new DocumentListener() {
      @Override
      public void changedUpdate(DocumentEvent e) {
           validate(e);
      }
      @Override
      public void removeUpdate(DocumentEvent e) {
            validate(e);
      }
      @Override
      public void insertUpdate(DocumentEvent e) {
           validate(e);
      }
      public void validate(DocumentEvent e) {
          String currText = "";
          try {
                Document doc = (Document) e.getDocument();
                currText = doc.getText(0, doc.getLength());
          } catch (BadLocationException e1) {
                e1.printStackTrace();
          }
          if (currText.contains("%")) { // To check if the field has key-in data or CardReader data
                Runnable doRun = new Runnable() {
                      @Override
                      public void run() {
                          try {
                            Thread.sleep(1000); // This delay is to make sure that the Card data is on the JTextField after a swipe
                            } catch (InterruptedException e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                            }                             
                          String check = userText.getText();
                          String s[] = check.split("[;=]");
                          if(s.length > 1){
                              System.out.println(s[1]);   //Extract the Card number                               
                              userText.setText("");                           
                              userText.setText(s[1]);
                              Thread.currentThread().interrupt();
                              //Thread.currentThread().isInterrupted();                               
                              return; 
                          }                              
                      }
                };                    
                SwingUtilities.invokeLater(doRun);                
                System.out.println("Checked");
          } ;                
      }
  });     
  JButton loginButton = new JButton("Check");
  loginButton.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {     
        String data = "Username " + userText.getText();
        data += ", Code: " 
        + new String(passwordText.getPassword()); 
        statusLabel.setText(data);        
     }
  }); 

EDIT: After the advice of Boris and RealSkeptic, here is the working code,

if (currText.contains("%")) { // To check if the field has key-in data or CardReader data
                /* Runnable doRun = new Runnable() {
                      @Override
                      public void run() {
                          try {
                            Thread.sleep(1000); // This delay is to make sure that the Card data is on the JTextField after a swipe
                            } catch (InterruptedException e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                            }                             
                          String check = userText.getText();
                          String s[] = check.split("[;=]");
                          if(s.length > 1){
                              System.out.println(s[1]);   //Extract the Card number                               
                              userText.setText("");                           
                              userText.setText(s[1]);
                              Thread.currentThread().interrupt();
                              //Thread.currentThread().isInterrupted();                               
                              return; 
                          }                              
                      }
                };                    
                SwingUtilities.invokeLater(doRun);   */                 
                SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>(){
                    protected Void doInBackground() throws Exception {
                        try {
                            Thread.sleep(1000); // This delay is to make sure that the Card data is on the JTextField after a swipe
                            } catch (InterruptedException e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                            }
                        String check = userText.getText();
                        String s[] = check.split("[;=]");
                        if(s.length > 1){
                          System.out.println(s[1]);   //Extract the Card number                               
                          userText.setText("");                           
                          userText.setText(s[1]); 
                        }                           
                        return null;
                    }
                };

                worker.execute();
                System.out.println("Checked");
          } ;
tapas
  • 1
  • 1
  • 1
    You're blocking the EDT with `invokeLater`. You need to use a `SwingWorker`. – Boris the Spider Apr 06 '15 at 10:30
  • 1
    You **must not** run long operations on the event dispatch thread (which is what `invokeLater` does). You need to use a swing worker. – RealSkeptic Apr 06 '15 at 10:32
  • Thank you @BoristheSpider for your advice. As I have never user SwingWorker before, it took me a while to put together the code. I am posting the working code next. – tapas Apr 08 '15 at 06:42
  • Thank you @RealSkeptic also for your advice. As I have never user SwingWorker before, it took me a while to put together the code. I am posting the working code next. – tapas Apr 08 '15 at 06:42
  • 1
    Swing is **not** threadsafe, and you must not access Swing components from any thread other than the EDT. This is exactly what you are doing by calling `setText` in `doInBackground`. I hate to say it, but this is **not** working code - it may work _for now_ but that is because you have a race hazard, which causes _random_ failures. You need to `publish` your updated `String` and then override `process` to update the GUI. Further, why are you calling `setText` twice? – Boris the Spider Apr 08 '15 at 07:05
  • @BoristheSpider, thank you again, i will fine tune to add override and rather than setText, publish i will. setText was twice just to see the behavior while i was using runnable. – tapas Apr 08 '15 at 08:56

0 Answers0