我有一个 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 毫秒。对于文档中的每次更改,计时器都会重新启动。
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/