2014-09-06 3 views
2

사용자 클릭 이외의 다른 곳에서 내 스윙 GUI를 업데이트하는 모든 프로세서는 EventQueue.invokeLater (예 : 장기 실행 백그라운드 비 EDT 스레드 프로세스에서 생성 된 출력)를 사용하여 수행됩니다.장기 실행 JEditorPane 처리를위한 모범 사례 setText process

현재 시나리오에서는 JEditorPane 개체를 업데이트해야하는 데이터를 반환하는 TCPIP 소켓 읽기 백그라운드 스레드 프로세스가 있습니다. JEditorPane setText 호출을 사용합니다. 문제는 invokeLater 루틴에 setText 호출을 배치하면 대용량 파일 (예 : 19,790KB)에 GUI가 고정됩니다.

이 문제를 해결하기위한 시도는 비 EDT 백그라운드 스레드에서 setText 동작을 수행하는 것입니다. 이것은 문제를 해결하는 것으로 보입니다. 다만, JEditorPane setText (Java JDK)는 thread 세이프가 아니기 때문에, 베스트 프랙티스가 걱정됩니다.

그러나 JDK 코드를 통해 트롤링하는 동안 여기에서 수행되는 긴 프로세스는 JDK DefaultEditorKit.read에 있으며 그 메소드 내에서 GUI에 영향을주는 유일한 코드는 doc.insertString 호출에 있습니다 (단, 오전). 이제는 JDK PlainDocument.java insertString 메소드를 보면 스레드 안전성을 문서화하므로이 솔루션이 건전하다고 생각할 것입니다. 그러나이

...

스트레스가 내 응용 프로그램을 테스트, 나는 GUI 주위에 어떤 임의의 클릭을하고, 현재 트리 노드 애니메이션이 실행되고, 아래의 큰로드하는 동안, 애니메이션을 느리게 나타납니다 않습니다 조금, 따라서 내가 가장 좋은 해결책을 수행하지 못했다는 나의 관심사 (또한 미래의 JRE가 나를 여기까지 망가 뜨리고 따라서 현재 스레드 세이프 상태 인 insertString에 의존하지 않는 것에 대해 매우 우려하고있다).

나는이 질문이 "오래 실행되는 JEditorPane setText를 처리하는 방법"에 대해 이전에 질문되었지만 적합한 대답이없는 것으로 조사했습니다.

질문 1) 내 현재 관측에 대한 생각을 가진 사람이 있습니까?

질문 2) 누구나 내가 이걸 어떻게 달성 할 수 있을지에 대한 아이디어가 있습니까?

참고 IDE 모양의 동적 글꼴을 지원하고 자연을 느낄 수 있기 때문에 JEditorPane 만 선택할 수 있습니다.

또한 아래의 호출은 EventQueue.invokeLater 루틴 내에서 호출되므로 초기 editorPane 작업은 EDT에 있습니다.

public void updateBigDataEditorPane(final JEditorPane editorPane, final String inStr) { 
    // Update editor object and content. 
    editorPane.setContentType("text/plain"); 
    editorPane.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N 
    editorPane.setDocument(editorPane.getEditorKit().createDefaultDocument()); 
    // Content update. NOTE in non-EDT thread to stop GUI freeze with large content. 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      //// synchronized 
      synchronized(tabsLock) { 
       // Set content. 
       editorPane.setText(inStr); 
      } //// synchronized 
     } 
    }).start(); 
} 
+0

SwingWorker를 사용하여 텍스트를 다운로드하고 적용된 완료 방법을 사용하십시오. – MadProgrammer

+0

@MadProgrammer SwingWorker는 위와 동일한 원칙을 적용합니다 (그리고 위의 정확성을 설정하면 SwingWorker 사용). 즉, setText는 EDT가 아니라 백그라운드에서 수행됩니다 (본질적으로 SwingWorker가 무엇에 관한 것입니까?). 그러면 EDT에 필요한 모든 게시 작업이 완료된 메서드에서 수행됩니다. 나는 그것이 당신이 의미하는 것이라고 가정합니다. 그렇지 않으면 setText를 SwingWorker done 메소드에 두는 것이 원래의 문제 코드와 동일한 효과를 가지므로 EDT에서 setText를 수행하면 GUI가 정지됩니다. 생각? –

+0

아니요. SwingWoker는 EDT와 업데이트를 동기화 할 수있는 게시/프로세스 방법을 제공합니다. 사실, UI를 업데이트하기 위해 EDT 내에서 호출되는 done 메소드를 사용하면됩니다. Swing은 일반적으로 스레드로부터 안전하지 않습니다. – MadProgrammer

답변

0

, 다음과 같이 내가 사용 결국 해결책이었다;

  1. 은, 시간의 setText 호출 완료에
  2. 소비를 수행하여 새로운 JEditorPane의 객체
  3. 만들기 새로 하나 생성과 GUI에 현재 활성화 된 JEditorPane의 객체를 대체합니다.

비 SwingWorker를 사용하여 백그라운드 비 EDT 작업 (1 & 2)을 수행 한 다음 EDT 스레드 완료시 3 단계를 수행하십시오.

0
당신은 (editorPane.getDocument()를 통해) EditorPane의 문서를 사용하여 다른 스레드에서 (대신의 setText (...)를 사용하는) ...의 insertString (통해)이 문서에 대한 변경 사항을 수행 할 수

.

이렇게하면 동적으로 (의미 : 읽는 동안) 내용을 쓸 수 있습니다.

예 (UI 동결하지 않고, Textpane에 파일에서 텍스트를 추가)과 같이
(편집 :이 새로운 코드는 테스트 하지이지만, 더 나은 내 제안을 증명해야한다 ...)에서 제공하는 답변이 도움이 있었고, 특정 장기 실행 EDT 스레드 요구 사항을 해결하기 위해 사용되는 동안

public void readFileAsync() 
{ 
    final String fileName = "/path/to/file.txt"; 
    final StyledDocument doc = yourTextPane.getStyledDocument(); 

    Runnable r = new Runnable() 
    { 
     public void run() 
     { 
      try 
      { 
       List<String> lines = Files.readAllLines(Paths.get(fileName), Charset.defaultCharset()); 
       for (String line : lines) 
       { 
        SwingUtilities.invokeLater(new Runnable() 
        { 
         public void run() 
         { 
          doc.insertString(doc.getLength(), line, null); 
         } 
        }); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
    Thread t = new Thread(r); 
    t.start(); 
} 
+0

스레드 sycnhronisation 상태가 최근에 변경되어 스레드 안전하지 않을 수 있습니다. – MadProgrammer

+0

@Ben이 문서에서 변경 작업을 수행하는 경우 : EDT를 통해 수행 한 경우 원래보고 된 것과 동일한 GUI 고정 문제가 있습니다. EDT 밖에서 수행 되었다면 필자가 원래 제안한 것과 동일한 해결책이됩니다. 단지 제안 된 솔루션이 EDT 외부에서 pre document insert 작업 (setText의 코드 및 위에서 설명한 읽기)을 수행한다는 유일한 차이점이 있습니다. –

+0

@MadProgrammer 지금 사용하고있는 JDK 7 버전에서 문서 insertString 메서드는 스레드 안전합니다. 위의 솔루션이 정상적이라면 JDK7 빌드 코드를 이후 JRE에서 제공하는 방법에 대해 조사해야합니다. havent는 downowotes의 공포를 위해 그 질문을 여기에 묻지 않을 것이다. –