1


倉庫管理(衣類の保管)用のソフトウェアに取り組んでいます。倉庫内のすべてのアイテムには、内部に rfid があり、一意の ID が文字列として保存されます。
ユーザーがアイテムからアンテナで rfid を読み取り、受け取った ID を GUI のいずれかに自動的に表示できるようにするモジュールを作成しようとしていますjLabels。アンテナは で PC と接続しrs232ます。
アンテナからデータを読み取るクラスを作成できましたが、正常に動作します。通信用のポートを開き、プロパティを設定し、利用可能な場合はデータを読み取ります ( 経由SerialPortEvent.DATA_AVAILABLE event)。
しかし、その後、問題が発生しました:
そのクラスのインスタンスを別のスレッドで実行したいので、アンテナはスキャンを待機し、スキャンのたびにjLabelがアイテムのIDに従って変更されます(後で、データベースに接続されたこのIDでより複雑な操作を行いますが、今は私どこかに表示したいだけです)。
Java の冒険を始めたばかりですが、マルチスレッドの処理方法がわかりません。
この場合、Netbeans GUI からスキャンを開始したいと思います。スキャンのjFrame進行中に、最後にスキャンした項目に従ってjFrame値を動的に更新する必要があります。シナリオ:ユーザーがボタンを押してスキャンを開始し、一定量のアイテムをスキャンすると、スキャンされた各アイテムの ID がjLabel

jLabel (jReadLabel)スキャン間の時間、およびスキャンが完了したときにユーザーがボタンを押して停止するため、アプリはスレッドをいつ停止するかを認識します。
ReadCOM クラス ( getChipID()) で getter メソッドを作成しましたが、イベントが発生するたびにデータを jFrame に渡す方法がわかりません。これが私がこれまでに行ったことです:

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のコードがあります(読み取りを開始および停止するボタン、失われた部分...):

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    
4

2 に答える 2

1

1) メソッドsetText()はスレッドセーフとして宣言されていますが、現在のスレッドが によってフリーズされなくなるまで機能しますThread.sleep(int)

2) メソッドはfromまたはにsetText()ラップされて機能しますが、これらの API の外部にある場合、イベントをロックする可能性がありますinvokeLater()Runnable#run()util.Timer#run()Thread.sleep(int)EventDispatchThread

3) から開いCommPortActionListener後、Swing GUI がフリーズするか、からのすべてのイベントがActionListener終了するまで責任を負いません。JLabel

4) バックグラウンド タスクに移動する (CommPort から値を読み取る) 必要があります。

  • CommPortからRunnable.Threadまたはから呼び出しutil.Timerます(その後、を使用してループを一時停止する必要はありませんThread.sleep()

しかし、最も良いので、使用することをお勧めします

  • から呼び出すと、メソッド内でまたはメソッドをSwingWorker使用してメソッドから出力したり、イベントを呼び出すことができますThread.sleep()util.TimerdoInBackground()publish()process()EDT
于 2012-04-12T11:40:58.727 に答える
1

シリアル ポート読み取りスレッドから、次のコマンドを実行します。

SwingUtilities.invokeLater(new Runnable() { public void run() {
  // code that updates the label's contents
}});

したがって、これはプッシュ アプローチです。rfid をプルするのではなく、GUI にプッシュし、そのようなコードがイベント ディスパッチ スレッド (EDT) で実行されるように特別な注意を払います。それinvokeLaterがそのためです。

于 2012-04-12T11:22:04.337 に答える