2012-10-31 16 views

Odpowiedz

2

Ok, to jest moje zdanie na ten problem ... (Nicea pytanie chociaż)

enter image description here

Jest mały rozpatrzenie trzeba mieć z tego rozwiązania. Zwróci częściowo wyświetlane linie.

public class TestTextArea { 

    public static void main(String[] args) { 
     new TestTextArea(); 
    } 

    public TestTextArea() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestTextAreaPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestTextAreaPane extends JPanel { 

     private JTextArea textArea; 
     private JTextArea viewText; 

     public TestTextAreaPane() { 
      setLayout(new GridLayout(2, 1)); 
      textArea = new JTextArea(20, 100); 
      textArea.setWrapStyleWord(true); 
      textArea.setLineWrap(true); 
      textArea.setText(loadText()); 

      viewText = new JTextArea(20, 100); 
      viewText.setWrapStyleWord(false); 
      viewText.setLineWrap(false); 
      viewText.setEditable(false); 

      JScrollPane scrollPane = new JScrollPane(textArea); 
      add(scrollPane); 

      add(viewText); 

      scrollPane.getViewport().addChangeListener(new ChangeListener() { 
       @Override 
       public void stateChanged(ChangeEvent e) { 
        if (textArea.getText().length() > 0) { 
         JViewport viewport = (JViewport) e.getSource(); 
         Rectangle viewRect = viewport.getViewRect(); 

         Point p = viewRect.getLocation(); 
         int startIndex = textArea.viewToModel(p); 

         p.x += viewRect.width; 
         p.y += viewRect.height; 
         int endIndex = textArea.viewToModel(p); 

         if (endIndex - startIndex >= 0) { 

          try { 
           viewText.setText(textArea.getText(startIndex, (endIndex - startIndex))); 
          } catch (BadLocationException ex) { 
           ex.printStackTrace(); 
           viewText.setText(ex.getMessage()); 
          } 

         } 

        } 

       } 
      }); 

     } 

     protected String loadText() { 
      String text = null; 
      File file = new File("src/testtextarea/TestTextArea.java"); 

      BufferedReader br = null; 
      try { 
       br = new BufferedReader(new FileReader(file)); 
       StringBuilder sb = new StringBuilder(128); 
       String read = null; 
       while ((read = br.readLine()) != null) { 
        sb.append(read).append("\n"); 
       } 

       text = sb.toString(); 
      } catch (IOException exp) { 
       exp.printStackTrace(); 
      } finally { 
       try { 
        br.close(); 
       } catch (Exception e) { 
       } 
      } 

      return text; 
     } 
    } 
} 
+0

+1 dla ładniejszego rozwiązania –

+0

Wygląda na to, że viewToModel() jest drogą do zrobienia. Dzięki. – Ma99uS

5

Ciekawe pytanie, które mi zajęło, ale myślę, że mam dość ważny odpowiedź. Jednak mogą istnieć lepsze sposoby; zachęcamy do komentowania, aby poprawić odpowiedź.

Stategy:

  1. Znajdź których rzędy są widoczne przy użyciu FontMetrics i getVisibleRect()
  2. znaleźć zawartość widzialnego rzędach.

Tak więc, moim pomysłem jest, że powinniśmy zacząć od widocznego recta. Na tej podstawie możemy dowiedzieć się, co jest pierwszym widocznym pionowym przesunięciem (getVisibleRect().y) i końcem widocznego przesunięcia pionowego (getVisibleRect().y+getVisibleRect().height). Kiedy już to zrobimy, za pomocą wysokości czcionki możemy ustalić, które rzędy są widoczne.

Druga część jest dowiedzieć się, co robi te wiersze zawierają. To tutaj używam Utilities z getRowStart() i getRowEnd() wchodzi w grę.

Oto przykładowy kod z czego się detalami (wynik są wyprowadzane do konsoli, jak zmienić rozmiar ramki lub przewijania textarea):

import java.awt.event.AdjustmentEvent; 
import java.awt.event.AdjustmentListener; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingUtilities; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.Utilities; 

public class TestTextAre { 

    private void initUI() { 
     JFrame frame = new JFrame(TestTextAre.class.getSimpleName()); 
     final JTextArea ta = new JTextArea(5, 25); 
     ta.setText("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has " 
       + "been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of " 
       + "type and scrambled it to make a type specimen book.\n It has survived not only five centuries, but also the " 
       + "leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the" 
       + " release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing " 
       + "software like Aldus PageMaker including versions of Lorem Ipsum."); 
     ta.setColumns(20); 
     ta.setEditable(false); 
     ta.setLineWrap(true); 
     ta.setWrapStyleWord(true); 
     JScrollPane scrollpane = new JScrollPane(ta); 
     scrollpane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { 

      @Override 
      public void adjustmentValueChanged(AdjustmentEvent e) { 
       if (e.getValueIsAdjusting()) { 
        return; 
       } 
       printTAVisibleInfo(ta); 
      } 
     }); 
     frame.add(scrollpane); 
     frame.addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentResized(ComponentEvent e) { 
       printTAVisibleInfo(ta); 

      } 

     }); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    private void printTAVisibleInfo(final JTextArea ta) { 
     List<Row> taInfo = getTAInfo(ta); 
     int y1 = ta.getVisibleRect().y; 
     int y2 = y1 + ta.getVisibleRect().height; 
     int lineHeight = ta.getFontMetrics(ta.getFont()).getHeight(); 
     int startRow = (int) Math.ceil((double) y1/lineHeight); 
     int endRow = (int) Math.floor((double) y2/lineHeight); 
     endRow = Math.min(endRow, taInfo.size()); 
     System.err.println(startRow + " " + endRow); 
     for (int i = startRow; i < endRow; i++) { 
      System.err.println(taInfo.get(i) + " is visible"); 
     } 
    } 

    private List<Row> getTAInfo(final JTextArea ta) { 
     List<Row> taInfo = new ArrayList<TestTextAre.Row>(); 
     int start = 0; 
     int end = -1; 
     int i = 0; 
     try { 
      do { 
       start = Utilities.getRowStart(ta, end + 1); 
       end = Utilities.getRowEnd(ta, start); 
       taInfo.add(new Row(i, start, end, ta.getDocument().getText(start, end - start))); 
       i++; 
      } while (end < ta.getDocument().getLength()); 

     } catch (BadLocationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return taInfo; 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new TestTextAre().initUI(); 
      } 
     }); 
    } 

    public static class Row { 
     private final int row; 
     private final int start; 
     private final int end; 
     private final String text; 

     public Row(int row, int start, int end, String text) { 
      super(); 
      this.row = row; 
      this.start = start; 
      this.end = end; 
      this.text = text; 
     } 

     public int getRow() { 
      return row; 
     } 

     public int getStart() { 
      return start; 
     } 

     public int getEnd() { 
      return end; 
     } 

     public String getText() { 
      return text; 
     } 

     @Override 
     public String toString() { 
      return "Row " + row + " contains " + text + " (" + start + "," + end + ")"; 
     } 
    } 

} 

Jeśli masz również poziomy pasek przewijania, myślę powinieneś być w stanie obliczyć poziome przesunięcia z FontMetrics.stringWidth().

+1

+1 ale łatwiej jest użyć metody viewToModel() uboczny widoczny prostokąt y zamiast obliczania z parametrów czcionki – StanislavL

+0

@StanislavL Tak masz rację. Rozwiązanie MadProgrammer jest bardziej eleganckie. –