سؤال

لدي الرمز التالي:

    listModel = new DefaultListModel();
    listModel.addElement(dateFormat.format(new Date()) + ": Msg1");
    messageList = new JList(listModel);
    messageList.setLayoutOrientation(JList.VERTICAL);

    messageScrollList = new JScrollPane(messageList);
    messageScrollList.setPreferredSize(new Dimension(500, 200));

    messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    }); 

انها تتم التمرير التلقائي لأسفل. ولكن ، إذا حاولت التمرير مرة أخرى لإعادة قراءة رسالة ، فإنها تجبر التمرير لأسفل. كيف يمكنني اصلاح هذا؟

هل كانت مفيدة؟

المحلول

عند إضافة رسالة جديدة ، استدعاء scrollRectToVisible() على ال JList باستخدام Rectangle وجود نفس الأبعاد مثل الحجم المفضل لجعة رسالتك. بالنظر إلى اتجاه رأسي ، قد يكون من المناسب جعل الحجم المفضل لـ JScrollPaneJViewport مضاعف لا يتجزأ من ارتفاع جزء الرسائل. أنظر أيضا: كيفية استخدام أجزاء التمرير.

إضافة: هذه المناقشة المقنعة لـ تم التمرير منطقة النص قد يكون مفيدًا أيضًا.

نصائح أخرى

لقد وجدت هذا مفيدًا حقًا:http://forums.sun.com/thread.jspa؟threadid=623669 (Post by 'Inopia')
إنه يعمل بشكل مثالي

كما يقول: "المشكلة هنا هي أنه قد يصبح من الصعب بعض الشيء العثور على حدث يطلق النار بعد تحديث كل من ListModel و JList و JScrollpane."

this.list = blah blah... 
this.list.setSelectedValue(whatever);   
final JScrollPane sp = new JScrollPane(this.list); // needs to be after the parent is the sp 
this.list.ensureIndexIsVisible(this.list.getSelectedIndex());

Question Enquirer. الرجاء تغيير الرمز الخاص بك من

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getMaximum());  
        }
    });

إلى

messageScrollList.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
        public void adjustmentValueChanged(AdjustmentEvent e) {  
            e.getAdjustable().setValue(e.getAdjustable().getValue());  
        }
    }); 

هذا هو التغيير getMaximum() إلى getValue() ثم يعمل كما هو مطلوب. getMaximum() يأخذ التمرير إلى أقصى حد ؛ في حين getValue() يأخذه أينما يحدث الحدث.

يمكنك تجنب استخدام قطعة الكود هذه تمامًا إذا وضعت سطرًا واحدًا

messageScrollList.setViewportView(messageList);

هذا يعمل مثل add(component) لـ JLILD ويحصل على سلوكه المتأصل.

للتمرير التلقائي ، أستخدم مفهومًا بسيطًا جدًا للمتغير الثابت والقائمة.

    public class autoScrollExample
    {
     static int index=0;
     private void someFunction()
     /*   
     * 
     */
     list1.add("element1");
     list1.makeVisible(index++);
     /*
     *
     */

     private void someOtherFunction()
     /*   
     * 
     */
     list1.add("element2");
     list1.makeVisible(index++);
     /*
     *
     */


    }

إستعملت JScrollPane مع JTextArea. لقد تجنبت القوة للتمرير لأسفل عن طريق التمرير فقط عندما JScrollBar max تغيرت القيمة:

        JScrollPane scrollPane = new JScrollPane(jTextArea);

        verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
        scrollPane.getVerticalScrollBar().addAdjustmentListener(
                e -> {
                    if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0)
                        return;
                    e.getAdjustable().setValue(e.getAdjustable().getMaximum());
                    verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum();
                });

أفترض أن هناك حلًا أفضل لتصفية الأحداث دون متغيرات إضافية ، وسوف نقدر إذا قام شخص ما بنشره.

أعتقد أن ما تريد القيام به هو أن تتم التمرير لأسفل عند إضافة أشياء إلى Messagelist ، بدلاً من ذلك عند التعديل. لذلك يمكن أن يبدو الرمز الخاص بك هكذا:

Adjustable sb = messageScrollList.getVerticalScrollBar()
boolean onBottom = sb.getValue() == sb.getMaximum();
//
// add your message to the JList.
//
if(onBottom)  sb.setValue(sb.getMaximum());

وإلا فإنك ستحتاج إلى معرفة ما إذا كان التعديل ناتجًا عن تغيير النموذج ، أو بسبب الماوس ، والنظر في مستندات API ، لست متأكدًا مما إذا كانت هناك طريقة للقيام بذلك بسهولة. على الرغم من أنه يمكنك معرفة ما إذا كان AdjustmentEvent.getAdjustmentType() إرجاع قيم مختلفة في تلك الحالات ، إذا كان هذا صحيحًا ، فيمكنك فقط الحصول على عبارة if في فئتك الداخلية المجهولة.

شيء آخر يمكن أن تجربه هو أن يكون هناك متغير منطقي في مكان ما يتم تعيينه عند إضافة شيء إلى القائمة. ثم ، في معالجك ، يمكنك التحقق لمعرفة ما إذا كان المتغير تم تعيينه. إذا كان الأمر كذلك ، فأنت تقوم بالتعديل (وتوضيح المتغير) وإلا ، فأنت تتجاهله. وبهذه الطريقة ، سيكون هناك تمرير واحد فقط لكل عنصر يتم إضافته إلى القائمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top