문제점:
JScrollPane 에 JTextArea를 붙인후, JTextArea의 크기보다 텍스트양이 많을때 스크롤을 생기게했다. 이때 파일에서 텍스트를 읽어 한번에 JTextArea에 넣으면 스크롤이 맨 아래로 내려가는데, 이것을 자동으로 맨위로 올라가게끔 하려했음. 그러기위해 JScrollPane 에서 getVerticalScrollBar()를 통해 JScrollBar의 객체를 반환 받았다. 그리고 JScrollBar의 메소드인 setValue(0)를 통해 스크롤의 위치를 조정할려 했으나.. 반응이 없음.. setValue()를 준후, getValue()를 통해 값을 확인해봐도 값이 변화가 없음.

해결법:
SwingUtilities.invokeLater()을 통해서 해결...

Runnable doScroll = new Runnable() {
   public void run() {
    textScrollPanel.getVerticalScrollBar().setValue(0);
   }
  };
  SwingUtilities.invokeLater(doScroll);


원인(추측):
java 의 swing은 동시에 여러작업이 진행되나보다, 프로그램 문장순서대로 바로바로 결과가 도출되는것이 아닌, 즉 흔히 말하는 결과값이 올때까지 기다리는 동기적실행이(?) 아닌, 결과가 오지 않더라고 계속 명령문장들을 보내고.. 또한 이 문장들역시  순서대로 실행되는것이 아닌 랜덤하게 또는 어떠한 진행방식에 의해 실행된다는 느낌이다.
 
결국 내가보낸 스크롤바와 관련된 실행문장들이 스크롤이 실제도 내려가기전에 실행되고, 이후에 스크롤이 자동으로 내려가는것 같다.  값은 정상적으로 들어가지만, 내가 원하는 순서대로 실행이 되는것이 아니므로 GUI에선 스크롤이 맨 아래로 내려간다.

이러한 현상을 테스트를 해보고자 JTextArea의 내용을 수정하는 명령문 이후에 Thread.sleep()을 통해 프로그램을 잠시 멈추게 해보았다. 결과는 명령문과 반대과 Thread.sleep() 이후에 JTextArea의 텍스트가 수정되었다. 

따라서, 이것을 해결하고자 인터넷 검색을 해보니 SwingUtitlites.invokeLater() 메소드를 통해 내가 보내는 명령이 나중에 실행되게끔 하는 방법이 존재했다.

다음은 java 6 API에 나온 invokeLater()의 내용임..

invokeLater

public static void invokeLater(Runnable  doRun)
doRun.run()를, AWT 이벤트발송쓰레드로 비동기적으로 실행시킵니다. 이것은, 보류중의 모든 AWT 이벤트가 처리된 뒤에 발생합니다. 이 메소드는, 어플리케이션 thread가 GUI 를 갱신할 필요가 있을 때 사용됩니다. 다음의 예에서는,invokeLater 호출은 이벤트발송쓰레드에 Runnable 객체의 doHelloWorld 의 큐를 호출하고 나서, 메세지를 출력합니다.
 Runnable doHelloWorld = new Runnable() {
     public void run() {
         System.out.println("Hello World on " + Thread.currentThread());
     }
 };

 SwingUtilities.invokeLater(doHelloWorld);
 System.out.println("This might well be displayed before the other message. ");
 
invokeLater 가 이벤트발송쓰레드, 예를 들어 JButton 의 ActionListener 로부터 불려 갔을 경우, doRun.run()는 보류중의 모든 이벤트가 처리될 때까지 실행이 연기됩니다. 다만, doRun.run()가 캐치 되지 않는 예외를 throw 하는 경우는, 이벤트발송쓰레드 (현재의 thread는 아니다)가 상태를 바탕으로 되돌립니다.  

이 메소드의 추가의 문서와 예에 대해서는, 「The Java Tutorial」의「How to Use Threads」 를 참조해 주세요.  

JDK Version 1.3 이후, 이 메소드는 java.awt.EventQueue.invokeLater() 로만 사용됩니다.  

이 메소드는, 다른 Swing 의 메소드와는 달라, 어느 thread로부터에서도 호출할 수 있습니다.

관련 항목:
invokeAndWait(java.lang.Runnable)

Posted by sangmooni
,