java - 完成对 JTextField 的条码扫描后执行操作

标签 java swing timer jtextfield javax.swing.timer

我有一个 JTextField barcodeTextField,它接受使用条形码扫描仪扫描的条形码中的字符。据我所知,条形码扫描就像快速键入字符或将字符复制粘贴到文本字段上一样。 barcodeTextField 还用于显示建议并用信息填充其他字段(就像在 Google 中搜索一样,在您键入时会显示建议)。

到目前为止,我使用 DocumentListener 实现了这一点:

barcodeTextField.getDocument().addDocumentListener(new DocumentListener() {
  public void set() {
    System.out.println("Pass");
    // Do a lot of things here like DB CRUD operations.
  }

  @Override
  public void removeUpdate(DocumentEvent arg0) {
    set();
  }

  @Override
  public void insertUpdate(DocumentEvent arg0) {
    set();
  }

  @Override
  public void changedUpdate(DocumentEvent arg0) {
    set();
  }
});

问题是:如果扫描的条形码有13个字符,set()会执行13次,DB操作也是如此。当我输入“123”显示建议列表时也是如此,set() 执行了 3 次。

我希望当用户停止在 barcodeTextField 上键入时执行 set()。在 Javascript/JQuery 中,这可以使用 keyup() 事件并在用户仍在输入时使用 setTimeout() 方法、clearTimeout() 来完成。

如何在 Java 中为 JTextField 实现此行为?

最佳答案

"Is there any way to obtain the string entered on JTextField when the user stops typing"

同样的,Javascript有超时,Swing有定时器。因此,如果您正在寻找的内容是在 Javscript 中使用其“计时器”功能实现的,您可以看看是否可以使用 Swing Timers 来让它工作。

例如Timer有一个restart 。因此,您可以将计时器的延迟设置为 1000 毫秒。输入文本后(文档中的第一次更改),请检查 if (timer.isRunning()) ,如果是的话,则 timer.restart() ,否则 timer.start() (意味着文档中的第一次更改)。仅当文档更改后一秒过去后,计时器才会执行操作。在第二秒结束之前发生的任何进一步变化都将导致计时器重置。并设置timer.setRepeats(false),使操作仅发生一次

您的文档监听器可能看起来像这样

class TimerDocumentListener implements DocumentListener {

    private Document doc;
    private Timer timer;

    public TimerDocumentListener() {
        timer = new Timer(1000, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (doc != null) {
                    try {
                        String text = doc.getText(0, doc.getLength());
                        statusLabel.setText(text);
                    } catch (BadLocationException ex) {
                        Logger.getLogger(TimerDemo.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        });
        timer.setRepeats(false);
    }

    public void insertUpdate(DocumentEvent e) { set(e); }
    public void removeUpdate(DocumentEvent e) { set(e); }
    public void changedUpdate(DocumentEvent e) { set(e); }

    private void set(DocumentEvent e) {
        if (timer.isRunning()) {
            timer.restart();
        } else {
            this.doc = e.getDocument();
            timer.start();
        }
    }
}

这是一个完整的示例,我通过以 500 毫秒的受控间隔显式插入文本字段的文档(九个数字)来“模拟”键入。可以在DocumentListener拥有的Timer中看到延迟为1000毫秒。因此,只要发生输入,DocumentListener 计时器就不会执行其操作,因为延迟超过 500 毫秒。对于文档中的每次更改,计时器都会重新启动。

enter image description here

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

public class TimerDemo {

    private JTextField field;
    private JLabel statusLabel;

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            public void run() {
                new TimerDemo();
            }
        };
        SwingUtilities.invokeLater(runnable);
    }

    public TimerDemo() {
        JFrame frame = new JFrame();
        frame.setLayout(new GridLayout(0, 1));

        field = new JTextField(20);
        field.getDocument().addDocumentListener(new TimerDocumentListener());
        statusLabel = new JLabel(" ");

        JButton start = new JButton("Start Fake Typing");
        start.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                startInsertTimer();
            }
        });

        frame.add(field);
        frame.add(statusLabel);
        frame.add(start);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void startInsertTimer() {
        Timer timer = new Timer(500, new ActionListener() {
            private int count = 9;

            public void actionPerformed(ActionEvent e) {
                if (count == 0) {
                    ((Timer) e.getSource()).stop();
                } else {
                    Document doc = field.getDocument();
                    int length = doc.getLength();
                    try {
                        doc.insertString(length, Integer.toString(count), null);
                    } catch (BadLocationException ex) {
                        Logger.getLogger(TimerDemo.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    count--;
                }
            }
        });
        timer.start();
    }

    class TimerDocumentListener implements DocumentListener {

        private Document doc;
        private Timer timer;

        public TimerDocumentListener() {
            timer = new Timer(1000, new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (doc != null) {
                        try {
                            String text = doc.getText(0, doc.getLength());
                            statusLabel.setText(text);
                        } catch (BadLocationException ex) {
                            Logger.getLogger(TimerDemo.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            });
            timer.setRepeats(false);
        }

        public void insertUpdate(DocumentEvent e) { set(e); }
        public void removeUpdate(DocumentEvent e) { set(e); }
        public void changedUpdate(DocumentEvent e) { set(e); }

        private void set(DocumentEvent e) {
            if (timer.isRunning()) {
                timer.restart();
            } else {
                this.doc = e.getDocument();
                timer.start();
            }
        }
    }
}

关于java - 完成对 JTextField 的条码扫描后执行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26651047/

相关文章:

Java验证扫描仪输入

java - 如何验证 java 对象从一种状态到另一种状态的转换[两种状态都是用户定义的]?

java - 如何在 JFrame 上的 JOptionPane 中显示我输入的内容?

c# - ASP.NET - 添加新行后刷新 gridview(DataTable 源)(由计时器触发)

python:如何在多线程中发送数据包然后线程自行终止

java - 如何从输入文件中查找平均值、中位数、众数和极差?

linux - 在linux+openJDK中运行struts+tomcat6应用程序报错

java - JTable 中的列名未更新

java - 如何在 JPanel 更新时使 JScrollPane 滚动

vb.net - 需要每 30 秒触发一个与系统时钟同步的定时器