1


저는웨어 하우스 관리 (옷 보관 용) 소프트웨어를 연구 중입니다. 웨어 하우스의 모든 항목에는 내부에 rfid가 있으며 고유 ID는 String으로 저장됩니다.
사용자가 안테나로 항목에서 rfid를 읽고 GUI의 jLabels 중 하나에 수신 된 ID를 자동으로 표시 할 수있게 해주는 모듈을 만들려고합니다. 안테나는 rs232에 의해 PC와 연결됩니다.
나는 안테나에서 데이터를 읽는 클래스를 만들었고 잘 동작한다. 통신을위한 포트를 열어 등록 정보를 설정하고 사용 가능한 경우 데이터를 읽습니다 (SerialPortEvent.DATA_AVAILABLE event 통해).
하지만 문제가 발생했습니다 :
안테나가 스캔을 기다리고 스캔 할 때마다 jLabel이 항목 ID에 따라 변경 될 수 있도록 해당 클래스의 인스턴스를 다른 스레드에서 실행하고 싶습니다. (나중에 복잡한 작업을 수행 할 예정입니다. 이 ID에 대한 작업은 내 데이터베이스와 연결되어 있지만 이제는 어딘가에 표시되기를 원합니다.)
Java 모험을 시작할 때 멀티 스레딩을 처리하는 방법을 모르겠습니다.
이 경우에는 Netbeans GUI jFrame에서 스캔을 시작하고 스캔이 진행되는 동안 jFrame은 마지막으로 스캔 한 항목에 따라 jLabel의 값을 동적으로 새로 고쳐야합니다.
시나리오 :
사용자가 버튼을 눌러 스캔을 시작하고 일부 항목을 스캔하며 스캔 된 항목의 ID는 스캔 사이에 jLabel (jReadLabel)으로 이동하고 스캔이 완료되면 버튼을 눌러 중지합니다. 그러면 앱에서 언제 중지할지 알 수 있습니다. 실.
ReadCOM 클래스 (getChipID())에서 getter 메서드를 만들었지 만 이벤트가 발생할 때마다 jFrame에 데이터를 전달하는 방법을 모르겠습니다. 직렬 포트에서받은 데이터에 따라 Java 동적 변경 jLabel 텍스트

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  
+1

이벤트를 호출하면 방법 publish()에서 방법 doInBackground() 출력 내부 Thread.sleep() 또는 util.Timer를 사용하거나 process()가 될 수있다 그럴 때. 를 호출하는 대신'Thread.sleep (n)'은 작업 반복을위한 Swing 타이머를 구현하거나 장시간 실행되는 작업을위한 SwingWorker를 구현합니다. 자세한 내용은 [동시성 (Concurrency in Swing)] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)을 참조하십시오. (조금 후에, 그러나 '연결'로). –

답변

1

1 방법 setText()는 스레드로부터 안전 선언하지만 전까지 현재의 thread가

2) 방법 setText() 작품 Runnable#run() 또는 util.Timer#run()에서 invokeLater()에 랩, Thread.sleep(int)에 의해 얼어 붙었다하지만 Thread.sleep(int) 그 API를 밖에되지 않는 작동합니다) 다음 잠재적으로 EventDispatchThread

3) ActionListener에서 CommPort을 여는 이벤트를 고정 할 수 있습니다, 다음 GUI는 동결 또는 ActionListener이 종료로부터 전까지 모든 이벤트는, 아무것도 ㄱ 없었다 unresponsible없는 스윙 전자는 ) Thread.sleep()을 사용하여 다음 필요하지 일시 중지 루프 (Runnable.Thread 또는 util.Timer에서 CommPort를 호출하는 배경 작업

  • 에의 CommPort에서 (읽기 값)를 이동해야)

    4 JLabel에 dispayed

    하지만 더 나은 대부분 나는

    • 내가를 사용하는 게 좋을 것 GUI를 것이다 '동결'- nvoke SwingWorker에서, 다음 EDT (이벤트 발송 쓰레드)를 막지 마십시오 EDT
+0

늦어서 미안 해요, 자동차 사고로 거의 한 달 동안 부상당했습니다. :/팁 주셔서 감사합니다. @mKorbel - 그게 내가 필요로하는 바로 그거야! 내가 이벤트 처리기 내에서 게시 (chip_id)와 SwingWorker 접근 방식을 사용하고 지금은 완벽하게 작동합니다. 건배. – demo

+0

기꺼이 도와 드리겠습니다. – mKorbel

1

이 실행 :

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

그래서 푸시 방식 : 당신은 RFID를 잡아 당기지 마십시오, 당신은 GUI, 타킨에 밀어 넣습니다 g 이러한 코드는 Event-Dispatching Thread (EDT)에서 실행됩니다. 그것은 invokeLater을위한 것입니다.