使用Java中的DocumentFilter进行条形码扫描

时间:2017-03-15 01:45:17

标签: java swing barcode-scanner documentfilter

我的条形码包括"1039723170303CC15-78" 我使用DocumentFilter的原因是我想将数量限制为7 digit。 其余的数字会自动转到第二个textField。

我的代码只能设置7位数,而不是所有其余的数字都转到下一个文本字段。 (即"1039723"转到第一个textField而"70303CC15-78"转到第二个textFiled。"1"在第二个textFiled中丢失。

我该如何解决这个问题?

lblTest = new JLabel("Testing : ");
panel.add(lblText, "cell 0 1,alignx trailing");

txtTest = new JTextField(7);

 AbstractDocument d = (AbstractDocument) txtTest.getDocument();
 d.setDocumentFilter(new DocumentFilter() {
     @Override  
        public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException  
        {
            if(fb.getDocument().getLength()+string.length()>7)
            {                       
                return;                     
            }
            fb.insertString(offset, string, attr);                  
        }  


        @Override  
        public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException 
        {                   
            fb.remove(offset, length);
        }


        @Override  
        public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs)throws BadLocationException 
        {  
                 if(fb.getDocument().getLength()+text.length()>7)
                 {
                     txtTest.transferFocus();
                    System.out.println("print.." +txtTest.getText());
                    return;
                }
                fb.insertString(offset, text, attrs);
        }
 });
打印输出:

print Mo No.:1039723
print Mo No.:1039723
print Mo No.:1039723

1 个答案:

答案 0 :(得分:0)

您遇到的基本问题是,您检查的text已被丢弃,并且从未应用于任何内容。

例如,如果输入的文本是(假设一次只有一个字符)123456789,则8将被忽略,因为9将被发送到另一个字段。

您需要做的是,使用您要忽略的文本手动设置下一个字段的文本。

现在,你的当前有两个基本缺陷。

  1. 没有考虑replace应删除任何选定字符的事实
  2. 如果文字被追加到字段
  3. ,则不会考虑会发生什么
  4. 不考虑文本是否插入字段末尾以外的偏移量
  5. 此示例尝试回答所有这些问题

    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    import javax.swing.text.AbstractDocument;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.DocumentFilter;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame("Test");
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                JTextField field1 = new JTextField(7);
                JTextField field2 = new JTextField(7);
                ((AbstractDocument) field1.getDocument()).setDocumentFilter(new LimitDocumentFilter(field2));
                add(field1);
                add(field2);
            }
    
        }
    
        public class LimitDocumentFilter extends DocumentFilter {
    
            private JTextField next;
    
            public LimitDocumentFilter(JTextField next) {
                this.next = next;
            }
    
            @Override
            public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
                super.insertString(fb, offset, text, attr);
                String textValue = fb.getDocument().getText(0, fb.getDocument().getLength());
                if (textValue.length() > 7) {
                    remove(fb, 7, fb.getDocument().getLength() - 7);
                    String overflow = textValue.substring(7);
                    next.requestFocusInWindow();
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            next.setText(overflow);
                            next.setCaretPosition(overflow.length());
                        }
                    });
                }
            }
    
            @Override
            public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
                fb.remove(offset, length);
                insertString(fb, offset, text, attrs);
            }
        }
    
    }
    

    这真正需要的是委托模型,而不是DocumentFilter更改字段焦点,它将该责任委托给其他观察者,并将溢出文本传递给

    更新

    好的,这是一个更新版本,它提供了三种可以设置文本的方法:

    1. 直接通过setText
    2. 从剪贴板粘贴
    3. 通过Robot
    4. 注入键盘缓冲区的击键

      这提供了条码扫描器“可能”工作方式的最佳示例

      import java.awt.AWTException;
      import java.awt.Robot;
      import java.awt.Toolkit;
      import java.awt.datatransfer.Clipboard;
      import java.awt.datatransfer.StringSelection;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.event.FocusListener;
      import java.awt.event.KeyEvent;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Map;
      import java.util.Set;
      import java.util.logging.Level;
      import java.util.logging.Logger;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.JTextField;
      import javax.swing.SwingUtilities;
      import javax.swing.UIDefaults;
      import javax.swing.UIManager;
      import javax.swing.text.AbstractDocument;
      import javax.swing.text.AttributeSet;
      import javax.swing.text.BadLocationException;
      import javax.swing.text.DocumentFilter;
      import javax.swing.text.DocumentFilter.FilterBypass;
      
      public class Test {
      
          public static void main(String[] args) {
              new Test();
          }
      
          public Test() {
              SwingUtilities.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      JFrame frame = new JFrame("Test");
                      frame.add(new TestPane());
                      frame.pack();
                      frame.setLocationRelativeTo(null);
                      frame.setVisible(true);
                  }
              });
          }
      
          public class TestPane extends JPanel {
      
              public TestPane() {
                  JTextField field1 = new JTextField(7);
                  JTextField field2 = new JTextField(7);
                  LimitDocumentFilter filter = new LimitDocumentFilter();
                  filter.add(new LimitListener() {
                      @Override
                      public void limitReached(LimitDocumentFilter filter, String overflow) {
                          // This is to overcome the issue of MacOS autoselecting the
                          // text when it gets focus ... dumb
                          FocusListener[] listeners = field2.getFocusListeners();
                          for (FocusListener listener : listeners) {
                              field2.removeFocusListener(listener);
                          }
                          field2.setText(overflow);
                          field2.requestFocusInWindow();
                          field2.setCaretPosition(overflow.length());
                          SwingUtilities.invokeLater(new Runnable() {
                              @Override
                              public void run() {
                                  for (FocusListener listener : listeners) {
                                      field2.addFocusListener(listener);
                                  }
                              }
                          });
                      }
                  });
                  ((AbstractDocument) field1.getDocument()).setDocumentFilter(filter);
                  add(field1);
                  add(field2);
      
                  JButton sim = new JButton("Simulate");
                  sim.addActionListener(new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent e) {
                          field1.setText(null);
                          field2.setText(null);
                          field1.requestFocusInWindow();
                          SwingUtilities.invokeLater(new Runnable() {
                              @Override
                              public void run() {
                                  Thread t = new Thread(new Simulator());
                                  t.start();
                              }
                          });
                      }
                  });
                  JButton paste = new JButton("Paste");
                  paste.addActionListener(new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent e) {
                          field1.setText(null);
                          field2.setText(null);
                          String text = "1234567abcdefg";
                          Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                          clipboard.setContents(new StringSelection(text), null);
                          field1.requestFocusInWindow();
                          SwingUtilities.invokeLater(new Runnable() {
                              @Override
                              public void run() {
                                  field1.paste();
                              }
                          });
                      }
                  });
                  JButton set = new JButton("Set");
                  set.addActionListener(new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent e) {
                          field1.setText(null);
                          field2.setText(null);
                          field1.setText("1234567abcdefghijklmnopqrstuvwxyz");
                      }
                  });
      
                  add(sim);
                  add(paste);
                  add(set);
              }
      
          }
      
          public class Simulator implements Runnable {
      
              @Override
              public void run() {
                  try {
                      Robot bot = new Robot();
                      type(KeyEvent.VK_1, bot);
                      type(KeyEvent.VK_2, bot);
                      type(KeyEvent.VK_3, bot);
                      type(KeyEvent.VK_4, bot);
                      type(KeyEvent.VK_5, bot);
                      type(KeyEvent.VK_6, bot);
                      type(KeyEvent.VK_7, bot);
      
                      type(KeyEvent.VK_A, bot);
                      type(KeyEvent.VK_B, bot);
                      type(KeyEvent.VK_C, bot);
                      type(KeyEvent.VK_D, bot);
                      type(KeyEvent.VK_E, bot);
                      type(KeyEvent.VK_F, bot);
                      type(KeyEvent.VK_G, bot);
                  } catch (AWTException ex) {
                      ex.printStackTrace();
                  }
              }
      
              protected void type(int keyStoke, Robot bot) {
                  bot.keyPress(keyStoke);
                  bot.keyRelease(keyStoke);
              }
      
          }
      
          public interface LimitListener {
      
              public void limitReached(LimitDocumentFilter filter, String overflow);
          }
      
          public class LimitDocumentFilter extends DocumentFilter {
      
              private List<LimitListener> listeners = new ArrayList<>(25);
      
              public LimitDocumentFilter() {
              }
      
              public void add(LimitListener listener) {
                  listeners.add(listener);
              }
      
              public void remove(LimitListener listener) {
                  listeners.remove(listener);
              }
      
              protected void limitReached(String overflow) {
                  for (LimitListener listener : listeners) {
                      listener.limitReached(this, overflow);
                  }
              }
      
              @Override
              public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
                  super.insertString(fb, offset, text, attr);
                  String textValue = fb.getDocument().getText(0, fb.getDocument().getLength());
                  if (textValue.length() > 7) {
                      remove(fb, 7, fb.getDocument().getLength() - 7);
                      String overflow = textValue.substring(7);
                      limitReached(overflow);
                  }
              }
      
              @Override
              public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
                  fb.remove(offset, length);
                  insertString(fb, offset, text, attrs);
              }
          }
      
      }