2011-11-23 17 views
9

मेरे पास एक बड़े पैनल के साथ एक स्विंग ऐप है जो JScrollPane में लपेटा गया है। उपयोगकर्ता आमतौर पर टैबबिंग द्वारा पैनल के सबकंपोनेंट्स के बीच स्थानांतरित होते हैं, इसलिए जब वे किसी चीज़ को देखने के लिए टैब करते हैं, तो मैं स्क्रॉल फलक को ऑटोस्कोलर करना चाहता हूं ताकि इनपुट फोकस वाला घटक हमेशा दिखाई दे।मैं इनपुट फोकस का पालन करने के लिए JScrollPane स्क्रॉल कैसे बना सकता हूं?

मैंने इनपुट फोकस परिवर्तनों को सुनने के लिए KeyboardFocusManager का उपयोग करने का प्रयास किया है, और फिर scrollRectToVisible पर कॉल किया है।

यहाँ एक SSCCE मेरे वर्तमान रणनीति प्रदर्शित है (बस कॉपी/पेस्ट और चलाने!):

import java.awt.KeyboardFocusManager; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import javax.swing.*; 

public class FollowFocus { 

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

     public void run() { 
     final int ROWS = 100; 
     final JPanel content = new JPanel(); 
     content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); 
     content.add(new JLabel(
      "Thanks for helping out. Use tab to move around.")); 
     for (int i = 0; i < ROWS; i++) { 
      JTextField field = new JTextField("" + i); 
      field.setName("field#" + i); 
      content.add(field); 
     } 

     KeyboardFocusManager.getCurrentKeyboardFocusManager() 
          .addPropertyChangeListener("focusOwner", 
        new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent evt) { 
      if (!(evt.getNewValue() instanceof JComponent)) { 
       return; 
      } 
      JComponent focused = (JComponent) evt.getNewValue(); 
      if (content.isAncestorOf(focused)) { 
       System.out.println("Scrolling to " + focused.getName()); 
       focused.scrollRectToVisible(focused.getBounds()); 
      } 
      } 
     }); 

     JFrame window = new JFrame("Follow focus"); 
     window.setContentPane(new JScrollPane(content)); 
     window.setSize(200, 200); 
     window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     window.setVisible(true); 
     } 
    }); 
    } 
} 

आप इस उदाहरण चलाते हैं, तो आप इसे बहुत अच्छी तरह से काम नहीं करता है पर ध्यान देंगे। यह फोकस परिवर्तन अधिसूचनाएं प्राप्त करता है, लेकिन scrollRectToVisible पर कॉल का कोई प्रभाव नहीं दिखता है। मेरे ऐप में (जो यहां दिखाने के लिए बहुत जटिल है), scrollRectToVisible आधे समय तक काम करता है जब मैं व्यूपोर्ट के बाहर कुछ में टैब करता हूं।

क्या इस समस्या को हल करने के लिए एक स्थापित तरीका है? यदि इससे कोई फर्क पड़ता है, तो स्विंग ऐप नेटबीन्स आरसीपी पर बनाया गया है (और हमारे अधिकांश ग्राहक विंडोज चलाते हैं)।

उत्तर

13

अन्य जवाब देने के लिए मेरे टिप्पणी:

scrollRectToVisible घटक पर ही है कि विधि ;-) के पूरे मुद्दे यह पदानुक्रम ऊपर से पारित कर दिया गया है जब तक एक माता पिता स्क्रॉल कर

... पाया जाता है को छोड़कर जब घटक ही यह संभालती है - JTextField करता है: यह horizo ​​स्क्रॉल करने के लिए लागू हो जाता है देखभाल को दृश्यमान बनाने के लिए। क्षेत्र के माता-पिता पर विधि को कॉल करना तरीका है।

संपादित

सिर्फ स्पष्टता के लिए, प्रतिस्थापित लाइन

content.scrollRectToVisible(focused.getBounds()); 
+0

स्पष्टीकरण के लिए धन्यवाद। –

+5

हां, स्पष्टीकरण के लिए धन्यवाद। आपका प्रस्तावित फिक्स मेरे ऐप में काम नहीं करता है (हालांकि यह ऊपर दिए गए उदाहरण में एक आकर्षण की तरह काम करता है), लेकिन थोड़ी सी प्रयोग के बाद मुझे निम्नलिखित काम मिल गया: '((जेकंपोनेंट) केंद्रित .getParent()) scrollRectToVisible (focused.getBounds()) 'अब, कोई भी साँस लेने या ध्यान केंद्रित अनुयायी टूट जाता है ...;) – gustafc

0

अपने कोड में एक प्रमुख मुद्दा है:

focused.scrollRectToVisible(focused.getBounds()); 

आप घटक पर ही scrollRectToVisible बुला रहे हैं! संभवतः एक टाइपो। अपने jScrollPane एक अंतिम चर करें और फोन

scrollPane.getViewport().scrollRectToVisible(focused.getBounds()); 
+0

scrollRectToVisible घटक पर ही यह एक माता पिता जब तक पदानुक्रम ऊपर से पारित कर दिया गया है कि विधि ;-) की _whole point_ है स्क्रॉल कर रहा है – kleopatra

+0

@ क्लेओपत्रा मुझे यह नहीं पता था।मैंने जो बदलाव प्रस्तावित किया वह ठीक काम करता है लेकिन मुझे नहीं पता कि यह क्यों काम नहीं करता है। –

+0

मेरा उत्तर के रूप में क्यों (केवल टिप्पणी पोस्ट करने के बाद घटक के प्रकार के नोटिस किया था) _do not_ संदेश कोड विवेक के लिए व्यूपोर्ट सीधे देख फिर भी, – kleopatra

3

आप भी JPanel और JViewPort से Rectangle ले, तो तुलना, उदाहरण के

सूचना के लिए करना पड़ता है (नीचे के खिलाफ -वॉटिंग) अंतिम और अच्छे आउटपुट के लिए JViewPort

में पदों के लिए कुछ काम की आवश्यकता है
import java.awt.KeyboardFocusManager; 
import java.awt.Rectangle; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import javax.swing.*; 
//http://stackoverflow.com/questions/8245328/how-do-i-make-jscrollpane-scroll-to-follow-input-focus 
public class FollowFocus { 

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

      public void run() { 
       final int ROWS = 100; 
       final JPanel content = new JPanel(); 
       content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); 
       content.add(new JLabel(
         "Thanks for helping out. Use tab to move around.")); 
       for (int i = 0; i < ROWS; i++) { 
        JTextField field = new JTextField("" + i); 
        field.setName("field#" + i); 
        content.add(field); 
       } 
       final JScrollPane scroll = new JScrollPane(content); 
       KeyboardFocusManager.getCurrentKeyboardFocusManager(). 
         addPropertyChangeListener("focusOwner", new PropertyChangeListener() { 

        @Override 
        public void propertyChange(PropertyChangeEvent evt) { 
         if (!(evt.getNewValue() instanceof JComponent)) { 
          return; 
         } 
         JViewport viewport = (JViewport) content.getParent(); 
         JComponent focused = (JComponent) evt.getNewValue(); 
         if (content.isAncestorOf(focused)) { 
          System.out.println("Scrolling to " + focused.getName()); 
          Rectangle rect = focused.getBounds(); 
          Rectangle r2 = viewport.getVisibleRect(); 
          content.scrollRectToVisible(new Rectangle(rect.x, rect.y, (int) r2.getWidth(), (int) r2.getHeight())); 
         } 
        } 
       }); 

       JFrame window = new JFrame("Follow focus"); 
       window.setContentPane(new JScrollPane(content)); 
       window.setSize(200, 200); 
       window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       window.setVisible(true); 
      } 
     }); 
    } 
} 
+0

नहीं, तुम एक) किसी भी अतिरिक्त आयत हेरफेर ख की जरूरत है) अंतिम क्षेत्र – kleopatra

+0

न है ख पर थोड़ा पीछे हटने के लिए) - के संदर्भ में स्क्रॉलिंग के लिए सामग्री की आवश्यकता नहीं है, यह जांचने के लिए आवश्यक है कि फोकस सामग्री के बाल पदानुक्रम में है या नहीं – kleopatra

0

यहाँ jtextbox घटक आप ध्यान केंद्रित करना चाहते हैं और jScrollPane अपने Scrollpane है:

jScrollpane.getVerticalScrollBar().setValue(jtextbox.getLocation().x); 
संबंधित मुद्दे

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