2017-11-30 6 views
0

3 개의 RS232 직렬 포트에서 데이터를 읽는 소프트웨어를 작성하려고합니다. 프로그램에서 실제로 수신중인 포트에 대한 시각적 피드백을 제공하는 코드를 작성했습니다. 프로그램이 COM1에서 듣고 있다는 것을 알고 있습니다. 콘솔에서 어떤 포트를 듣고 있는지 알려주고 있습니다. 문제는 실제 GUI에서 사용자에게 알리기 위해 JTextFields를 업데이트하지 않는다는 것입니다. 그것은 오직 NONE에 "listenState"필드를 설정하고 있지 업데이트 할 것 몇 가지 이유를 들어JTextField가 직렬 포트에서 업데이트되지 않습니다

if (Serial.currPortId == (null)) { 
     listenState.setText("NONE"); 
     listenState.revalidate(); 
    } 
    while (Serial.currPortId != (null)) { 
     listenState.setText(Serial.currPortId.getName()); 
     listenState.revalidate(); 
     if (Serial.currPortId.getName().equals("COM1")) { 
      tab1sheet.setText(ImportMenu.serialImport.datafeed); 
      tab1sheet.revalidate();} 
     else if (Serial.currPortId.getName().equals("COM2")) { 
      tab2sheet.setText(ImportMenu.serialImport.datafeed); 
      tab2sheet.revalidate();} 
     else if (Serial.currPortId.getName().equals("COM3")) { 
      tab3sheet.setText(ImportMenu.serialImport.datafeed); 
      tab3sheet.revalidate();} 
     else {tab1sheet.setText("N/A"); 
       tab1sheet.revalidate(); 
       tab2sheet.setText("N/A"); 
       tab2sheet.revalidate(); 
       tab3sheet.setText("N/A"); 
       tab3sheet.revalidate();} 
     } 

, 콘솔에서 COM1을 듣고 주장에도 불구하고 다음과 같이 내가 작성한 코드입니다.

답변

1

코드가 스윙 스레딩 규칙을 위반합니다. Swing 이벤트 스레드에서 청취 코드를 실행하려고 시도했을 수 있습니다 (게시 한 스 니펫을 기반으로 말할 수는 없지만) 스레드의 텍스트 필드를 잘못 업데이트하려고합니다. 대신, SwingWorker를 사용하여 백그라운드 스레드의 포트를 수신하는 것이 좋습니다. 특히 SwingWorker<Void, String> 게시/처리 메소드 쌍을 사용하여 JTextArea에 텍스트를 전송하는 것이 좋습니다. 또는 GUI의 여러 위치로 이동하는보다 복잡한 정보로 GUI를 업데이트해야하는 경우 PropertyChangeListener를 SwingWorker에 연결하여 작업자 상태에 대한 변경 사항을 리스너 (GUI)에 알립니다.

class MyWorker extends SwingWorker<Void, Void> { 
    // properties to listen for changes to: 
    public static final String LISTEN_STATE = "listen state"; 
    public static final String CURRENT_PORT_ID = "current port id"; 
    public static final String DATA_FEED = "data feed"; 
    private String listenState = "None"; 
    private String dataFeed = ""; 
    private String currentPortId = ""; 

    @Override 
    protected Void doInBackground() throws Exception { 
     while (true) { 
      if (Serial.currPortId != (null)) { 
       // change properties when data comes in 
       String currPortId = Serial.currPortId.getName(); 
       setListenState(currPortId); 
       setCurrentPortId(currPortId); 
       setDataFeed(ImportMenu.serialImport.datafeed); 
      } else { 
       setListenState("None"); 
       break; // ?? 
      } 
     } 
     return null; 
    } 

    public String getListenState() { 
     return listenState; 
    } 

    public void setListenState(String listenState) { 
     // set the prop change parameters 
     String oldValue = this.listenState; 
     String newValue = listenState; 

     // update the propertie's state 
     this.listenState = listenState; 

     // notify listeners of the change 
     firePropertyChange(LISTEN_STATE, oldValue, newValue); 
    } 

    public String getDataFeed() { 
     return dataFeed; 
    } 

    public void setDataFeed(String dataFeed) { 
     // same rationale as for the other setter method 
     String oldValue = this.dataFeed; 
     String newValue = dataFeed; 
     this.dataFeed = dataFeed; 
     firePropertyChange(DATA_FEED, oldValue, newValue); 
    } 

    public String getCurrentPortId() { 
     return currentPortId; 
    } 

    public void setCurrentPortId(String currentPortId) { 
     // same rationale as for the other setter method 
     String oldValue = this.currentPortId; 
     String newValue = currentPortId; 
     this.currentPortId = currentPortId; 
     firePropertyChange(CURRENT_PORT_ID, oldValue, newValue); 
    } 
} 

그런 다음 다음 변화에 대응하고 리스너를 부착 할 수는 GUI

에 표시를 갱신 자세한 내용은

, Lesson: Concurrency in Swing

귀하의 코드는 다음과 같이 뭔가을 볼 수 있었다 체크 아웃

private class MyWorkerListener implements PropertyChangeListener { 
    @Override 
    public void propertyChange(PropertyChangeEvent evt) { 
     switch (evt.getPropertyName()) { 
     case MyWorker.LISTEN_STATE: 
      String listenState = evt.getNewValue().toString(); 
      // show in text field 
      break; 
     case MyWorker.CURRENT_PORT_ID: 
      String currentPortId = evt.getNewValue().toString(); 
      // use this to decide which tab to change to 
      break; 
     case MyWorker.DATA_FEED: 
      String dataFeed = evt.getNewValue().toString(); 
      // show where needed 
      break; 

     default: 
      break; 
     } 
    } 
} 

그리고 gui에 다음과 같이 연결합니다.

MyWorker worker = new MyWorker(); 
worker.addPropertyChangeListener(new MyWorkerListener()); 
worker.execute(); 

당신은 또한 SwingWorker.StateValue.DONE NEWVALUE을 수신하기 위해 SwingWorker의 또 다른 PropertyChangeListener를 추가 할, 그리고이 발생하면 트랩에 작업자 get()를 호출하고 예외를 처리 할 것

나 '
+0

이걸 보게, 고마워! 청취 코드는 "직렬"을 통해 여기에서 호출되는 다른 클래스에서 실행됩니다. 업데이트하는 경우에 불과합니다. 직렬 포트에 대한 많은 경험이 없기 때문에 모든 것을 배울 수 있습니다. –

+0

@JosephOliver :하지만 백그라운드 스레드에서 청취 코드를 실행하고 있습니까? 그렇지 않은 경우 코드가 완전히 응답하여 완전히 응답하지 않을 것으로 예상합니다. –

+0

@JosephOliver : 불완전한 예를 들어 답을 편집하십시오. –

관련 문제