2012-01-30 7 views
1

현재 MySQL 데이터베이스에서 쿼리를 실행하는 유틸리티를 개발 중이며 현재 인터페이스에서 작업 중입니다.JTextField가 올바르게 업데이트되지 않았습니다.

사용자가 "연결"버튼을 클릭하면 상태 표시 줄 (JTextField) 텍스트가 "연결 중 ..."으로 변경됩니다. 이 올바르게 작동 :

connectButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      statusBar.setText("Connecting..."); 
      } 
     } 
    }); 

내가 다음 데이터베이스에 연결하는 기능을 구현 한 "연결"버튼을 클릭 :이 경우

connectButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      Class.forName("com.mysql.jdbc.Driver"); 
      statusBar.setText("Connecting..."); 
      connection = DriverManager.getConnection("jdbc:mysql://" + database); 
      } 
     } 
    }); 

, 상태 표시 줄의 텍스트를 변경하지 않습니다 연결이 설정 될 때까지 "연결 중 ..."으로 변경하십시오.

가독성 향상을 위해 예외 처리와 같은 일부 코드가 제거되었습니다.

연결이 설정되기 전에 상태 표시 줄의 텍스트를 변경하려면 어떻게합니까?

+0

Kosir : [Concurrency In Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) 자습서는 다음과 같습니다. 감사합니다 –

답변

4

이벤트 발송 스레드에서 데이터베이스 연결을 설정하면 안됩니다. 이로 인해 구성 요소가 업데이트되지 않습니다. 대신, 백그라운드 스레드에서 작업을 수행하십시오.

이 작업이 수행되는 동안 결과를보고해야하는 경우 SwingWorker 클래스를 사용하거나 SwingUtilities 클래스, 특히 invokeLater을 사용하여 구성 요소를 업데이트하십시오. 이 두 가지 모두 구성 요소가 EDT에서 업데이트되고 장시간 실행되는 작업이 다른 곳에서 발생 함을 보장합니다.

자세한 내용은 Concurrency in Swing을 참조하십시오.

+0

그래, 고마워. SwingWorker를 사용하는 법을 배워야 할 것 같습니다. 좋은 자습서 나 간단한 예를 추천 해 주시겠습니까? –

+0

SwingWorker를 사용하려면 * 필요하지 않습니다. 스윙 스레드 모델을 이해하기 위해서는 * 필요합니다. : D – mre

1

EDT (AWT Event Dispatch Thread)에서 연결을 설정하기 때문입니다. 연결을 만드는 동안 사용자 입력을 처리하고 화면의 창을 다시 그리기 (그래픽으로)하는 작업은 더 이상 수행되지 않습니다. 즉, 연결이 설정 될 때까지 전체 응용 프로그램이 고정 된 것처럼 보입니다.
이렇게하려면 다른 스레드에서 연결을 만들어야합니다. 더러운 또 다른 권장 방법은 텍스트를 변경 한 후 EDT가 화면을 다시 칠하도록하는 것입니다. 이것은 가장 간단한 방법이지만 깔끔한 방법은 아닙니다.

이 작업은 repaint();을 호출 한 다음 update(getGraphics());을 호출하여 수행 할 수 있습니다. 그러나 그것은 매우 더러운입니다. 나는 당신의 화면이 깜빡 일 것이라고 생각한다. 그러나 이것은 문제를 잘 보여줍니다. 실제적으로 일어나는 것을보기 위해 이것을 먼저 테스트하는 것이 흥미로울 것입니다.

2

이 질문은 2 일마다 요청됩니다.

이벤트 발송 스레드에서 코드를 실행하면이 세 번째 스레드를 차단하므로 텍스트 필드에 텍스트가 표시되는 데 필요한 모든 다시 그리기 작업이 실행되지 않습니다.

블로킹 작업은 백그라운드 스레드에서 실행해야하며이 스레드는 스윙 구성 요소에 액세스 할 수 없습니다. SwingWorker을 사용하십시오. javadoc은 모든 것을 설명합니다. 또한 Swing 튜토리얼의 관련 섹션에 대한 링크가 있으므로 읽어보십시오.

3

다른 사람이 언급 한 것처럼 연결 논리는 이벤트 발송 스레드 이외의 스레드에서 수행하는 것이 가장 좋습니다. 그러나 기술적으로 이것이 연결이 설정 될 때까지 텍스트 필드가 업데이트되지 않는 이유는 아닙니다.

이런 이유 실제 이유는 내부 스윙 컴포넌트는 청취자가 그들이 첨가 순서 비교 역순 통지되어있다 (이 경우 ActionListener들) 수신기를 저장하는 데이터 구조를 사용하는 것이다. 따라서 귀하의 예에서 연결을 생성하는 ActionListener은 텍스트 업데이트를 담당하는 리스너보다 먼저 통지됩니다.

두 개의 ActionListener을 하나의 코드 블록으로 병합하는 것이 간단합니다. 여러 청취자를 추가 할 필요가 없습니다. 물론 연결을 시도하는 동안 GUI가 차단되므로 다른 사람이이를 방지하기 위해 SwingWorker과 같은 메커니즘을 사용하는 것이 좋습니다.

connectButton.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
    statusBar.setText("Connecting..."); 

    new SwingWorker<Void, Void>() { 
     protected Void doInBackground() { 
     // Called on a background thread. 
     connectToDatabase(); 
     return null; 
     } 

     protected void done() { 
     // Called on Event Dispatch thread once connect routine has completed. 
     try { 
      get(); // Propagate any exceptions back to Event Dispatch thread. 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      JOptionPane.showMessageDialog(null, 
      "Failed to connect: " + ex.getMessage(), 
      "Error", 
      JOptionPane.ERROR_MESSAGE); 
     } 
     } 
    }.execute(); 
    } 
}); 
+0

나는 청취자가 하나뿐입니다. 방금 여러 개를 지정 했으므로 내 문제를 이해할 수 있습니다. –

관련 문제