Java 8 如何从java中的另一个类中从事件侦听器检索值?
我有一个程序从条形码扫描仪(使用jssc库)获取值,它使用事件侦听器按预期返回值,但我需要从另一个类访问该值 我尝试将BarcodeScanner类实例化为main方法(ProcessTicket类),并调用scannerHandler方法,还调用model类的getter方法来检索值,但getter方法在扫描完成之前运行。你能帮我做到这一点吗Java 8 如何从java中的另一个类中从事件侦听器检索值?,java-8,event-listener,jssc,Java 8,Event Listener,Jssc,我有一个程序从条形码扫描仪(使用jssc库)获取值,它使用事件侦听器按预期返回值,但我需要从另一个类访问该值 我尝试将BarcodeScanner类实例化为main方法(ProcessTicket类),并调用scannerHandler方法,还调用model类的getter方法来检索值,但getter方法在扫描完成之前运行。你能帮我做到这一点吗 public class BarcodeScanner { public static Object SerialPor
public class BarcodeScanner {
public static Object SerialPortReader;
static SerialPort serialPort;
public void scannerHandler() {
serialPort = new SerialPort("COM4");
try{
serialPort.openPort();//Open serial port
//Set params. Also set params by this string:
serialPort.setParams(9600, 8, 1, 0);
serialPort.setParams(9600, 8, 1, 0);
serialPort.writeString(new String(new byte[]{0x02})); //triggers barcode scanner
serialPort.addEventListener(new SerialPortReader());//Add SerialPortEventListenerS
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
public static class SerialPortReader implements SerialPortEventListener {
String str;
String value;
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR() && event.getEventValue() > 0) {//If data is available
//Check bytes count in the input buffer
try {
byte[] bytesCont = serialPort.readBytes(14);
str = new String(bytesCont);
ModelClass modelClass = new ModelClass();
modelClass.setBarcodeValue(str);
} catch (SerialPortException e) {
e.printStackTrace();
}
}
}
我的ProcessTicket.java类
public class ProcessTicket {
public static void main(String[] args) throws SQLException, SerialPortException {
BarcodeScanner bSC = new BarcodeScanner();
bSC.scannerHandler();
BarcodeScanner.SerialPortReader portReader = new BarcodeScanner.SerialPortReader();
ModelClass modelClass = new ModelClass();
String value = modelClass.getBarcodeValue();
System.out.println(value);
}
}
这里的主要问题是,您将一个固有的异步操作(从现实世界中的外部传感器读取)视为同步操作 我模拟了外部传感器,制作了一个独立的应用程序来测试您的业务逻辑:
如何从另一个Classinjava.java中从EventListener中检索值
package com.stackoverflow;
/**
* https://stackoverflow.com/questions/57452205/how-to-retrieve-the-value-from-the-event-listener-from-another-class-in-java
*/
public class HowToRetrieveTheValueFromTheEventListenerFromAnotherClassInJava {
public static void main(String[] args) {
BarcodeScanner barcodeScanner = new BarcodeScanner((String barcode) -> {
System.out.println("Barcode scanned: " + barcode);
});
barcodeScanner.startScan();
MockUser.startScanningStuffLol();
}
}
package com.stackoverflow;
public interface BarcodeScannedCallback {
void callback(String barcode);
}
package com.stackoverflow;
public class BarcodeScanner implements SerialPortEventListener {
private SerialPort serialPort;
private final BarcodeScannedCallback callback;
public void startScan() {
try {
serialPort = new SerialPort("COM4");
serialPort.openPort();
serialPort.addEventListener(this);
// Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);
serialPort.setParams(9600, 8, 1, 0);
// Triggers barcode scanner.
serialPort.writeString(new String(new byte[]{0x02}));
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
@Override
public void serialEvent(SerialPortEvent event) {
boolean isDataAvailable = event.isRXCHAR() && event.getEventValue() > 0;
if (isDataAvailable) {
try {
byte[] bytesCont = serialPort.readBytes(14);
String barcode = new String(bytesCont);
callback.callback(barcode);
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
public BarcodeScanner(BarcodeScannedCallback callback) {
this.callback = callback;
}
}
调用MockUser.startScanningStuffLol()
是必要的,因为我只是在代码中测试,没有使用真正的条形码扫描仪。请不要专注于它。如果你要求的话,我会发布它的实现,但是我假设你的OS/Java/硬件按照设计的方式工作,你可以用这些工具而不是我的MockUser
软件模拟来测试它
以下是实现此功能所需的其他类:
BarcodeScannedCallback.java
package com.stackoverflow;
/**
* https://stackoverflow.com/questions/57452205/how-to-retrieve-the-value-from-the-event-listener-from-another-class-in-java
*/
public class HowToRetrieveTheValueFromTheEventListenerFromAnotherClassInJava {
public static void main(String[] args) {
BarcodeScanner barcodeScanner = new BarcodeScanner((String barcode) -> {
System.out.println("Barcode scanned: " + barcode);
});
barcodeScanner.startScan();
MockUser.startScanningStuffLol();
}
}
package com.stackoverflow;
public interface BarcodeScannedCallback {
void callback(String barcode);
}
package com.stackoverflow;
public class BarcodeScanner implements SerialPortEventListener {
private SerialPort serialPort;
private final BarcodeScannedCallback callback;
public void startScan() {
try {
serialPort = new SerialPort("COM4");
serialPort.openPort();
serialPort.addEventListener(this);
// Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);
serialPort.setParams(9600, 8, 1, 0);
// Triggers barcode scanner.
serialPort.writeString(new String(new byte[]{0x02}));
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
@Override
public void serialEvent(SerialPortEvent event) {
boolean isDataAvailable = event.isRXCHAR() && event.getEventValue() > 0;
if (isDataAvailable) {
try {
byte[] bytesCont = serialPort.readBytes(14);
String barcode = new String(bytesCont);
callback.callback(barcode);
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
public BarcodeScanner(BarcodeScannedCallback callback) {
this.callback = callback;
}
}
因为我们处理的是一个异步操作,我们不能像同步操作那样启动它然后检查返回值。相反,我们需要传入一个函数,该函数将在操作完成后被调用,然后等待它完成BarcodeScannedCallback
是该函数的签名(换句话说,描述该函数需要如何构造)。它只接受一个字符串参数,不返回任何内容
BarcodeScannedCallback
的实现就是我前面提到的这个函数,我将它传递到BarcodeScanner
构造函数中:
(String barcode) -> {
System.out.println("Barcode scanned: " + barcode);
}
如您所见,此函数接受一个字符串参数,但不返回任何内容。因此,它是BarcodeScannedCallback
接口的实现
现在来看最后一个类:使用上面的接口连接我们的main
方法和串行端口的类
BarcodeScanner.java
package com.stackoverflow;
/**
* https://stackoverflow.com/questions/57452205/how-to-retrieve-the-value-from-the-event-listener-from-another-class-in-java
*/
public class HowToRetrieveTheValueFromTheEventListenerFromAnotherClassInJava {
public static void main(String[] args) {
BarcodeScanner barcodeScanner = new BarcodeScanner((String barcode) -> {
System.out.println("Barcode scanned: " + barcode);
});
barcodeScanner.startScan();
MockUser.startScanningStuffLol();
}
}
package com.stackoverflow;
public interface BarcodeScannedCallback {
void callback(String barcode);
}
package com.stackoverflow;
public class BarcodeScanner implements SerialPortEventListener {
private SerialPort serialPort;
private final BarcodeScannedCallback callback;
public void startScan() {
try {
serialPort = new SerialPort("COM4");
serialPort.openPort();
serialPort.addEventListener(this);
// Also you can set params by this string: serialPort.setParams(9600, 8, 1, 0);
serialPort.setParams(9600, 8, 1, 0);
// Triggers barcode scanner.
serialPort.writeString(new String(new byte[]{0x02}));
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
@Override
public void serialEvent(SerialPortEvent event) {
boolean isDataAvailable = event.isRXCHAR() && event.getEventValue() > 0;
if (isDataAvailable) {
try {
byte[] bytesCont = serialPort.readBytes(14);
String barcode = new String(bytesCont);
callback.callback(barcode);
} catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
public BarcodeScanner(BarcodeScannedCallback callback) {
this.callback = callback;
}
}
下面是这些事件的整个生命周期:
- 您可以创建
条形码扫描仪
- 通过将
的实现传递到其构造函数中,告诉BarcodeScannedCallback
,一旦它通过串行端口接收到条形码,将运行什么代码BarcodeScanner
- 在
条形码扫描仪上调用
,打开串行端口并开始等待用户扫描条形码startScan
- 用户扫描条形码。该数据通过串行端口传输。操作系统实现的
调用SerialPort
BarcodeScanner.serialEvent
的实现执行验证,从串行端口提取数据并将其从字节转换为字符串,并调用开始时传入的serialEvent
函数BarcodeScannedCallback
MockUser
类设置了一个后台线程,每3秒“扫描”一次条形码),我得到以下输出:
Barcode scanned: 420L0L
Barcode scanned: 007
Barcode scanned: 12345
在您的情况下,您应该能够使用真实世界的条形码扫描仪扫描3个条形码,并获得相同的结果
请注意,您可能需要做一些事情来防止main
方法的线程过早结束,这取决于您运行该方法的上下文
如果您在Android应用程序或web服务器上运行它,这些框架将无限期地保持其主线程运行,直到您杀死应用程序/服务器
但是,如果您将其作为自定义命令行应用程序运行(基于
main
方法的存在,您似乎正在这样做),那么您需要做一些事情来保持它的活力,直到您决定杀死它为止。最简单的方法是放置一个无限循环,如while(true)
在main
方法的最后一行。在侦听器中创建一个返回所需内容的方法。当您在变量中创建侦听器对象并调用该方法时,请将其存储起来。您有一个“catch”,没有“try”。在开始考虑运行时错误之前,至少应该先编译代码。同样奇怪的是,一旦从端口读取,就会将结果放入这个“ModelClass”对象中,然后立即丢弃它,因为它是一个局部变量,并且方法结束。你希望它做什么?谢谢你的意见。我忘记粘贴try块,并在ProcessTicket上添加modelclass@Rogue如何在侦听器中创建方法?你能给我举个小例子吗。我仍然对event和actionlisteners很熟悉,就像任何其他类中的其他方法一样public int getMyInt(){return 42;}
。你想用什么方法都行,这是你的课。有关通用OOP编程的参考。具体到这个问题,请参阅“类和对象”部分。非常感谢您的详细解释。它正在按预期工作。我正在使用Javafx创建一个应用程序。当按下按钮并根据条形码从数据库中提取数据时,应触发条形码。