2012-10-31 9 views
8

पहली दृश्यमान रेखा की संख्या और स्क्रॉल करने योग्य JTextArea (JTextArea में JSCrollPane के अंदर) में दिखाई देने वाली लाइनों की संख्या कैसे निर्धारित करें?स्क्रॉल करने योग्य JTextArea में कौन सी रेखाएं दिखाई दे रही हैं यह निर्धारित करने के लिए कैसे?

उत्तर

2

ठीक है, इस समस्या पर मेरी ले ... (नाइस सवाल हालांकि)

enter image description here

वहाँ एक छोटा सा विचार आप इस समाधान के साथ की जरूरत है। यह आंशिक रूप से प्रदर्शित लाइनों वापस आ जाएगा।

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

निसर समाधान –

+0

के लिए +1 ऐसा लगता है कि ViewToModel() जाने का तरीका है। धन्यवाद। – Ma99uS

5

दिलचस्प सवाल है कि मुझे थोड़ी देर लग गई लेकिन मुझे लगता है कि मेरे पास एक वैध जवाब है। फिर भी कुछ बेहतर तरीके हो सकते हैं; उत्तर में सुधार करने के लिए टिप्पणी करने के लिए स्वतंत्र महसूस करें।

stategy:

  1. खोजें जो पंक्तियाँ दिखाई FontMetrics और getVisibleRect का उपयोग कर()
  2. दिखाई पंक्तियों की सामग्री का पता लगाएं हैं।

तो, मेरा विचार यह है कि हमें दृश्यमान आय से शुरू करना चाहिए। इसके आधार पर हम पता लगा सकते हैं कि पहला दृश्यमान लंबवत ऑफ़सेट (getVisibleRect().y) और दृश्य लंबवत ऑफ़सेट (getVisibleRect().y+getVisibleRect().height) का अंत क्या है। एक बार हमारे पास यह है कि, फ़ॉन्ट की ऊंचाई का उपयोग करके, हम निर्धारित कर सकते हैं कि कौन सी पंक्तियां दिखाई दे रही हैं।

दूसरा भाग यह पता लगाने के लिए है कि उन पंक्तियों में क्या शामिल है। यह वह जगह है जहां मैं UtilitiesgetRowStart() और getRowEnd() के साथ खेलता हूं।

यहाँ है कि मैं क्या का ब्यौरा दिया गया था का एक नमूना कोड है (परिणाम के रूप में आप फ़्रेम का आकार बदलने या पाठ क्षेत्र स्क्रॉल कंसोल के लिए उत्पादन कर रहे हैं):

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 + ")"; 
     } 
    } 

} 

आप भी एक क्षैतिज स्क्रॉलबार है, तो मुझे लगता है कि आप FontMetrics.stringWidth() के साथ क्षैतिज ऑफसेट की गणना करने में सक्षम होना चाहिए।

+1

+1 लेकिन यह viewToModel() विधि दिखाई आयत y गुजर बजाय फ़ॉन्ट मैट्रिक्स – StanislavL

+0

@StanislavL हाँ तुम ठीक कह रहे साथ गणना के दौरान उपयोग करना आसान है। MadProgrammer का समाधान अधिक सुरुचिपूर्ण है। –

संबंधित मुद्दे