首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java -根据从串口接收的数据动态改变jLabel文本

Java -根据从串口接收的数据动态改变jLabel文本
EN

Stack Overflow用户
提问于 2012-04-12 19:17:33
回答 2查看 1.6K关注 0票数 1

我正在开发仓库管理软件(用来存放衣服)。仓库中的所有物品都有rfid在里面,唯一的id以字符串形式存储。

我正在尝试使模块,将允许用户读取射频识别从项目的天线,并自动显示接收到的ID在图形用户界面的jLabels之一。天线通过rs232与PC机相连。

我已经设法让类从天线读取数据,它工作得很好。它打开通信端口,设置属性,并在可用时读取数据(通过SerialPortEvent.DATA_AVAILABLE event)。

但是我遇到了一个问题:

我希望类的实例在不同的线程中运行,因此天线将等待扫描,每次扫描后,jLabel将根据项目的ID进行更改(稍后我将对连接到数据库的ID进行更复杂的操作,但现在我只希望它显示在某个地方)。

我开始了我的Java探险,我不知道如何处理多线程。

在这种情况下,我想从我的Netbeans GUI jFrame开始扫描,并且在扫描过程中,jFrame应该根据上次扫描的项目动态刷新jLabel的值。

场景:

用户按下按钮开始扫描,扫描一定数量的项目,每个扫描项目的ID在两次扫描之间进入jLabel (jReadLabel),当扫描完成时,用户按下按钮停止,因此应用程序知道何时停止线程。

我已经在我的ReadCOM类(getChipID())中创建了getter方法,但我不知道如何在每次发生事件时将数据传递给jFrame。以下是我到目前为止所做的工作:

代码语言:javascript
复制
import java.io.*;
import java.util.*;
import javax.comm.*;

public class ReadCOM implements Runnable, SerialPortEventListener {

static CommPortIdentifier portId;
static CommPortIdentifier saveportId;
static Enumeration portList;
InputStream inputStream;
SerialPort serialPort;
public static Thread readThread;
static OutputStream outputStream;
static boolean outputBufferEmptyFlag = false;
public String defaultPort;
boolean isRunning = true;
private String chip_id="";

public CzytajCOM(CommPortIdentifier portId, String defaultPort) {

    this.defaultPort = defaultPort;
    try {
        serialPort = (SerialPort) portId.open("Magazyn", 2000);
    } catch (PortInUseException e) {
        System.out.println("Connection Error. Port in use.");
    }

    try {
        inputStream = serialPort.getInputStream();
    } catch (IOException e) {
    }

    try {
        serialPort.addEventListener(this);
    } catch (TooManyListenersException e) {
    }
    serialPort.notifyOnDataAvailable(true);
    try {
        serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);
    } catch (UnsupportedCommOperationException e) {
    }
    readThread = new Thread(this);
    readThread.start();       
}

public void initwritetoport() {

    try {
        outputStream = serialPort.getOutputStream();
    } catch (IOException e) {
    }

    try {
        serialPort.notifyOnOutputEmpty(true);
    } catch (Exception e) {
        System.exit(-1);
    }

}

public void writetoport() {
}

public void run() {

    while (isRunning) {
        try {
            while (isRunning) {
                Thread.sleep(100);
            }
        } catch (Exception e) {
            isRunning = false;
        }
    }
}

public void serialEvent(SerialPortEvent event) {
    switch (event.getEventType()) {
        case SerialPortEvent.BI:
        case SerialPortEvent.OE:
        case SerialPortEvent.FE:
        case SerialPortEvent.CD:
        case SerialPortEvent.CTS:
        case SerialPortEvent.DSR:
        case SerialPortEvent.RI:
            break;

        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
            break;

        case SerialPortEvent.DATA_AVAILABLE:

            Object obj = event.getSource();
            if (obj instanceof javax.comm.SerialPort) {
                serialPort = (SerialPort) obj;
                try {
                    BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(serialPort.getInputStream()));
                    chip_id = bufferedReader.readLine();
                    //System.out.println("Data: "+chip_id);
                    bufferedReader.close();
                } catch (Exception ex) {
                    System.out.println("Reading from device failed!");
                }
            }
            break;
    }
}

public boolean isRunning() {
    return isRunning;
}

public String getChipId() {
    return chip_id;
}

public void setIsRunning(boolean isRunning) {
    this.isRunning = isRunning;
}

}在我的jFrame文件中,下面是ButtonActionPerformed的代码(开始和停止阅读的按钮,我丢失的部分...):

代码语言:javascript
复制
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
     if(isRead==false) {
          jStatus.setText("Reading in progress...");
          jLabel1.setText("Press the button to stop reading.");
          isRead=true;
          try {
        portId1=CommPortIdentifier.getPortIdentifier("COM4");
        ReadCOM reader=new ReadCOM(portId1, portId1.getName());
        reader.setIsRunning(true); //
        jReadLabel.setText(reader.getChipId());
              }
    catch (Exception ex){
                    System.out.println("Error in button pressed method.");
                   }
     }
               else {

        jStatus.setText("Reading stopped.");
        jLabel1.setText("Press the button to start reading.");
        isRead=false;
    }
}//GEN-LAST:event_jButton1ActionPerformed    
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-12 19:40:59

1)方法setText()被声明为线程安全的,但在当前线程未被Thread.sleep(int)冻结之前有效,

2) method setText()可以从Runnable#run()util.Timer#run()封装到invokeLater()中,但您的Thread.sleep(int)在这些EventDispatchThread之外,那么可能会将事件锁定到API中

3)您从ActionListener打开CommPort,然后Swing GUI被冻结,或者直到来自ActionListener的所有事件结束时才是不负责任的,在JLabel中不会显示任何内容

4)你必须移动(从CommPort读取值)到后台任务

  • CommPortRunnable.Thread调用util.Timer (然后不需要使用Thread.sleep())

暂停循环

但更好的是,我建议使用

  • SwingWorker调用,然后您可以在方法doInBackground()中使用Thread.sleep()util.Timer,方法publish()process()的输出可以是EDT

上的调用事件

票数 1
EN

Stack Overflow用户

发布于 2012-04-12 19:22:04

从您的串行端口读取线程执行以下命令:

代码语言:javascript
复制
SwingUtilities.invokeLater(new Runnable() { public void run() {
  // code that updates the label's contents
}});

因此,这是一种推送方法:您不必拉出rfid,而是将其推送到GUI中,特别注意此类代码在事件分派线程(EDT)上执行。这就是invokeLater的作用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10122476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档