2014-09-04 6 views
3

JPanel을 포함하는 JScrollPane이 포함 된 JFrame이 있습니다. JPanel에는 JTextArea 개의 묶음이 들어 있습니다. 많은 텍스트를로드하고 있습니다 (약 8k-10k 문자).JScrollPane 및 JViewport의 최대 크기가 내용보다 작은 경우의 스크롤 제한

스크롤이 약간 뒤떨어 지지만 레이아웃이 잘 작동합니다.

진짜 문제는 JPanel, JScrollPaneJViewport 하드 32767 크기 제한이 보인다, 그래서 어떤 JTextArea이보다 높은 성장하면, 그것은 텍스트의 마지막 1/3을 보여 더를 스크롤 할 수 없습니다 .

아래에서 문제의 최소 예를 볼 수 있습니다.

public class NewJFrame extends javax.swing.JFrame { 

/** 
* Creates new form NewJFrame 
*/ 
public NewJFrame() { 
    initComponents(); 
} 

/** 
* This method is called from within the constructor to initialize the form. 
* WARNING: Do NOT modify this code. The content of this method is always 
* regenerated by the Form Editor. 
*/ 
@SuppressWarnings("unchecked") 
// <editor-fold defaultstate="collapsed" desc="Generated Code">       
private void initComponents() { 

    jScrollPane1 = new javax.swing.JScrollPane(); 
    jPanel1 = new javax.swing.JPanel(); 
    jTextArea1 = new javax.swing.JTextArea(); 
    jTextArea2 = new javax.swing.JTextArea(); 

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

    jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 
    jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 

    jTextArea1.setColumns(20); 
    jTextArea1.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N 
    jTextArea1.setRows(5); 

    jTextArea2.setColumns(20); 
    jTextArea2.setFont(new java.awt.Font("Monospaced", 0, 14)); // NOI18N 
    jTextArea2.setRows(5); 
    jTextArea2.setText("Some long text..."); 

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); 
    jPanel1.setLayout(jPanel1Layout); 
    jPanel1Layout.setHorizontalGroup(
     jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(jPanel1Layout.createSequentialGroup() 
      .addComponent(jTextArea1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
      .addComponent(jTextArea2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
      .addGap(0, 0, 0)) 
    ); 
    jPanel1Layout.setVerticalGroup(
     jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addGroup(jPanel1Layout.createSequentialGroup() 
      .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
       .addComponent(jTextArea1, javax.swing.GroupLayout.DEFAULT_SIZE, 342, Short.MAX_VALUE) 
       .addComponent(jTextArea2)) 
      .addGap(0, 0, 0)) 
    ); 

    jScrollPane1.setViewportView(jPanel1); 

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
    getContentPane().setLayout(layout); 
    layout.setHorizontalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addComponent(jScrollPane1) 
    ); 
    layout.setVerticalGroup(
     layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
     .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 96, Short.MAX_VALUE) 
    ); 

    pack(); 
}// </editor-fold>       

/** 
* @param args the command line arguments 
*/ 
public static void main(String args[]) { 
    final NewJFrame f = new NewJFrame(); 
    /* Set the Nimbus look and feel */ 
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> 
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 
    * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
    */ 
    try { 
     for(javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) 
      if("Nimbus".equals(info.getName())) { 
       javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
       break; 
      } 
    }catch(ClassNotFoundException ex) { 
     java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    }catch(InstantiationException ex) { 
     java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    }catch(IllegalAccessException ex) { 
     java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    }catch(javax.swing.UnsupportedLookAndFeelException ex) { 
     java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
    } 
    //</editor-fold> 

    /* Create and display the form */ 
    java.awt.EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      f.setVisible(true); 
     } 
    }); 
    StringBuilder txt = new StringBuilder(); 
    for(int i=0; i<10000; i++) 
     txt.append(i).append("\n"); 
    f.jTextArea1.setText(txt.toString()); 
    txt = new StringBuilder(); 
    txt.append("JTextArea height: ").append(f.jTextArea1.getHeight()).append('\n'); 
    txt.append("JTextArea rows: ").append(f.jTextArea1.getRows()).append('\n'); 
    txt.append("JScrollPane height:").append(f.jScrollPane1.getHeight()).append('\n'); 
    txt.append("JViewport height:").append(f.jScrollPane1.getViewport().getHeight()).append('\n'); 
    txt.append("JPanel height:").append(f.jPanel1.getHeight()).append('\n'); 
    f.jTextArea2.setText(txt.toString()); 
} 
// Variables declaration - do not modify      
private javax.swing.JPanel jPanel1; 
private javax.swing.JScrollPane jScrollPane1; 
private javax.swing.JTextArea jTextArea1; 
private javax.swing.JTextArea jTextArea2; 
// End of variables declaration     
} 
: 그것은 조금 길어질 수 있습니다하지만 기본값에서 변경된 유일한 것은이 JTextArea s는 JPanel 직접 아이들, 스크롤 정책 및 약간 큰 글꼴 크기 때문이다, 그래서 나는 넷빈즈에게 JFrame 디자이너를 사용

이것을 실행하고 아래로 스크롤하면 카운트가 10 000에 도달 할 것으로 예상되지만 1637로만 이동하므로 겨우 표시되는 다음 줄의 최상위 픽셀을 볼 수 있습니다.

나는 이미 JPanelsetMaximumSizesetSize에 시도의 JScrollPaneJViewport 아무것도하지만이 변경되었습니다. 또한 약간의 텍스트를 볼 수있을만큼 멀리 스크롤 할 수있는 10k 줄의 텍스트가 있지만 getRows()getSize() 메서드는 원래 값을 반환한다는 사실을 다소 혼란스러워합니다.

스크롤 할 수있는 JTextArea이 32767보다 큰 경우이 상황을 처리하는 올바른 방법은 무엇입니까?

+0

JViewport에 이러한 제한이있을 수 있다는 것을 믿을 수 없습니다. 나는 백만 개의 행을 가진 테이블을 개발했으며 매우 잘 스크롤 될 수있었습니다. 더 나은 도움을 얻을 수있는 실제 사례를 제공해주십시오. –

+0

Dimension – MadProgrammer

+0

의 요구 사항에 따라 하드 제한이 Interger.MAX_VALUE에 가까울 것이라고 생각합니다.이 [접근] (http://stackoverflow.com/a/25526869/230513)을 사용하면 'JTable' 플라이급 렌더링; 필요에 따라 사용자 정의 또는 팝업 셀 편집기를 사용하십시오. – trashgod

답변

1

이 문제는 스레드 안전성과 관련이 없습니다. 많이 파고 들자면, Look and Feel의 기본 윈도우 매니저 구현은 JPanel에 하드 코드 된 32767 크기 제한이 있다는 것을 알아 냈으므로 JScrollPane에 앉아있는 것이 중요하지 않습니다. 이 아이디어는 개별적인 많은 추가 관리를 피하는 것이었지만 그 한계로 인해 피할 수없는 것이되었습니다.

JPanel의 내용을 자신의 개인으로 이동하면 JscrollPane 님이 문제를 해결했습니다. 스크롤링은 아직 알려지지 않은 이유로 조금 뒤떨어져 있습니다.

2

initial thread에서 jTextArea2을 업데이트한다는 예가 잘못 동기화되었습니다. JTextArea#setText()은 더 이상 스레드로부터 안전하지 않습니다. 아래 예제에서는 (here 제안)을 호출하여 조사 된 here과 동일한 27MB, 176K 라인 파일을로드합니다. 이 작업은 몇 초 정도 걸리며 JTable 접근 방식의 약 두 배입니다. 그러나 스크롤링은 비슷합니다.

import java.awt.EventQueue; 
import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 

/** 
* @see https://stackoverflow.com/a/25691384/230513 
*/ 
public class Test { 

    private static final String NAME = "/var/log/install.log"; 

    private void display() { 
     JFrame f = new JFrame("Test"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JTextArea text = new JTextArea(24, 32); 
     try { 
      text.read(new BufferedReader(new FileReader(NAME)), null); 
     } catch (IOException ex) { 
      ex.printStackTrace(System.err); 
     } 
     f.add(new JScrollPane(text)); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      new Test().display(); 
     }); 
    } 
} 
+0

미안하지만이 일은 내가하려는 일이나 내가 준 예와 관련이 거의 없습니다. 스레드 안전성이'JTextArea'에서 텍스트 재설정에 문제가되는 것을 보지 못했습니다 - 나는'append() '를 전혀 사용하지 않고 있습니다. 비록 내가 그렇다하더라도, 나는 오직 메인 스레드가'JTextArea'에 쓰기 만하므로 왜 동기화 문제가 있는지 보지 못한다. 귀하의 예제는 내 문제를 전시하지 않지만 내가 갖고있는 레이아웃이 부족하여 실제로 도움이되지 않습니다. – nwod

+0

죄송 합니다만, 당신은'append()'에 대해 옳았 습니다만,'setText()'도 같은 문제가 있습니다; 업데이트되었습니다. 원하는 레이아웃을 사용할 수 있습니다. 이 예제는 스크롤 창에서 "약 8k-10k 문자"보다 훨씬 많은 텍스트를 처리 할 수 ​​있음을 보여줍니다. – trashgod

+1

+1 생성 된 모든 코드없이 'SSCCE'. '하지만 레이아웃이 부족하다'레이아웃이 문제 다. GroupLayout이하는 일을 누가 알겠습니까? 스크롤 판/패널/텍스트 영역이있는 구조를 만든 이유는 무엇입니까? 일반적으로 텍스트 영역은 스크롤 창에 직접 추가됩니다. 모든 그룹 레이아웃 코드와 패널을 제거하십시오. 그런 다음 스크롤 영역의 뷰포트에 텍스트 영역을 추가하기 만하면됩니다. 그런 다음 스크롤 패널을 BorderLayout.WEST에 추가하고 두 번째 텍스트 영역을 BorderLayout.EAST에 추가하십시오. – camickr