简体   繁体   English

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

[英]Barcode scanning using DocumentFilter in Java

My barcode include "1039723170303CC15-78" The reason I used DocumentFilter is I want to limit the number as 7 digit only. 我的条形码包括"1039723170303CC15-78"我使用DocumentFilter的原因是我想将7 digit限制为仅7 digit And the rest of the number goes to 2nd textField automatically. 其余的数字自动转到第二个textField。

My code only working set 7 digit only and not all the rest of the number goes to next textfield. 我的代码只能设置7位数而不是所有其余的数字都转到下一个文本字段。 (ie, "1039723" go 1st textField and "70303CC15-78" go 2nd textFiled. "1" is missing in the 2nd textFiled. (即"1039723"转到第一个textField和"70303CC15-78"转到第二个textFiled。第二个textFiled中缺少"1"

How can i solve this? 我怎么解决这个问题?

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 out put: 打印输出:

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

The basic problem you have, is the text you're checking is been discard and never applied to anything. 您遇到的基本问题是,您正在检查的text已被丢弃,并且从未应用于任何内容。

For example, if the text been entered is (assuming one character at a time) 123456789 , then 8 will be ignored, as 9 will be send to the other field. 例如,如果输入的文本是(假设一次一个字符) 123456789 ,那么将忽略8 ,因为9将被发送到另一个字段。

What you need to do, is manually set the text of the next field with the text you are going to ignore. 您需要做的是,使用您要忽略的文本手动设置下一个字段的文本。

Now, your current has a two fundamental flaws. 现在,你的当前有两个根本缺陷。

  1. It does not take into account the fact that replace should remove any selected characters 它没有考虑到replace应删除任何选定字符的事实
  2. Does not take into account what would happened if text was appended to the field 不考虑如果文本附加到字段会发生什么
  3. Does not take into account if text was inserted at an offset other than the end of the field 是否在字段末尾以外的偏移处插入文本时不考虑

This example attempts to answer all of those questions 此示例尝试回答所有这些问题

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);
        }
    }

}

What this really needs is a delegate model, where by instead of the DocumentFilter changing field focus, it delegates that responsibility to some other observer, passing it the overflow text 这真正需要的是委托模型,而不是DocumentFilter更改字段焦点,它将该责任委托给其他观察者,并将溢出文本传递给它

Update 更新

Okay, so this is an updated version which provides three ways that the text can be set: 好的,这是一个更新版本,它提供了三种可以设置文本的方法:

  1. Directly via setText 直接通过setText
  2. Pasted from the clipboard 从剪贴板粘贴
  3. Key strokes injected into the keyboard buffer via Robot 通过Robot将键击注入键盘缓冲区

This provides the best possible example of how a barcode scanner "might" work 这提供了条码扫描器“可能”如何工作的最佳示例

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);
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM