जेपीनल ऊंचाई तुरंत अपडेट नहीं होती है

मैं JSCrollPane के अंदर एक जेपीनल में एक छवि जोड़ने के लिए निम्न कोड का उपयोग कर रहा हूं। मैं स्क्रॉल फलक को नीचे स्क्रॉल करना चाहता हूं, लेकिन ऐसा लगता है कि थोड़ी देर बाद तक एक छवि को जोड़ा गया है, भले ही मैं इसे स्विंगउटिविटीज रैपर के अंदर बुला रहा हूं।

private void addImage(final String image){
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            imagePanel.addImage(image);
            final JScrollBar vScroll = imageScrollPane.getVerticalScrollBar();
            vScroll.setValue(vScroll.getMaximum());
        }
    });
}

ImagePanel से addImage कोड इस तरह दिखता है:

public void addImage(String image){
        System.out.println("Pre-height: " + getHeight());
        add(createImageLabel(image));
        System.out.println("After-height: " + getHeight());
        revalidate();
        System.out.println("Revalidate-height: " + getHeight());
    }

ऐसा लगता है कि यह परिणाम निम्न में है, उदाहरण के लिए:

Pre-height: 690
After-height: 690
Revalidate-height: 690

अगर मैं कॉल के बाद लूप में सोता हूं, तो वास्तव में ऊंचाई को बदलने के लिए 200 मीटर लगते हैं।

मेरे पास जो कोड है वह स्क्रॉल करते समय हमेशा 1 छवि को समाप्त करता है। इस तरह से नीचे स्क्रॉल करने के बारे में जाने का सबसे अच्छा तरीका क्या है कि मुझे वास्तव में पता है कि नीचे कहां है? मैं स्विंग सम्मेलनों के साथ केवल थोड़ी परिचित हूं, लेकिन मैंने सोचा कि चूंकि सब कुछ स्विंग यूटिलिटीज कॉल के अंदर हो रहा था, यह पता चलेगा कि यह क्या कर रहा था।

पूर्ण निष्पादन योग्य कोड उदाहरण जो समस्या का प्रदर्शन करता है:

package com.foo.bar

import java.awt.Dimension;
import java.awt.Image;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

import net.miginfocom.swing.MigLayout;

public class ScrollImageExampleFrame extends JFrame{

    private ScrollImageExamplePanel siePanel;

    public ScrollImageExampleFrame(){
        setSize(1024, 768);
        siePanel = new ScrollImageExamplePanel();
        getContentPane().add(siePanel);
    }

    class ScrollImageExamplePanel extends JPanel {
        ImageViewExamplePanel imagePanel = new ImageViewExamplePanel();
        JScrollPane imageScrollPane = new JScrollPane(imagePanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        public ScrollImageExamplePanel(){
            setLayout(new MigLayout("nogrid"));
            imageScrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(30, 0));
            add(imageScrollPane, "east, width 300!, height 100%");
        }

        private void addImageOuter(final String image){
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    imagePanel.addImageInner(image);
                    imagePanel.revalidate();
                    final JScrollBar vScroll = imageScrollPane.getVerticalScrollBar();
                    vScroll.setValue(vScroll.getMaximum());
                }
            });
        }
    }

    class ImageViewExamplePanel extends JPanel {
        public ImageViewExamplePanel() {
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        }

        public void addImageInner(String image){
            URL imageUrl = ImageViewExamplePanel.class.getResource("/com/foo/bar/" + image);
            ImageIcon ii = resizeImage(imageUrl, 360, 270);
            JLabel label = new JLabel();
            label.setIcon(ii);
            add(label);
            revalidate();
        }

        private ImageIcon resizeImage(URL url, int x, int y){
            Image image = null;
            try{
                image = ImageIO.read(url);
                Image newImage = image.getScaledInstance(x, y, Image.SCALE_SMOOTH);
                return new ImageIcon(newImage);
            } catch (IOException ioe){
                ioe.printStackTrace();
                return null;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ScrollImageExampleFrame frame = new ScrollImageExampleFrame();
        frame.setVisible(true);

        frame.siePanel.addImageOuter("foo.png");
        Thread.sleep(1000);
        frame.siePanel.addImageOuter("foo.png");
        Thread.sleep(1000);
        frame.siePanel.addImageOuter("foo.png");
        Thread.sleep(1000);
        frame.siePanel.addImageOuter("foo.png");        
    }

}
2
बेहतर सहायता के लिए जल्द ही एक एसएससीसीई पोस्ट करें, प्रदर्शन के रूप में आप वहां खाली जेपीनल डाल सकते हैं
जोड़ा लेखक mKorbel, स्रोत
ऊ। मेरा एसएससीसीई काम करता है कि मैं कैसे उम्मीद करूंगा। मैं यहां पूरी परियोजना को पेस्ट नहीं करना चाहता, लेकिन मैं पिन नहीं कर सकता कि क्यों मेरी परियोजना छवि जोड़ने और ऊंचाई को अपडेट करने में देरी देख रही है। अभी भी एक एसएससीसीई उत्पादन करने की कोशिश कर रहा है।
जोड़ा लेखक Alex Pritchard, स्रोत
घटक में कई छवियां होती हैं और इसमें अधिक जोड़ दिया जा सकता है। मैं जोड़े गए प्रत्येक छवि के लिए एक नया लेबल बना रहा हूं, लेकिन पुराने लेबल भी रहते हैं, क्योंकि मैं अभी भी उन छवियों को प्रदर्शित करना चाहता हूं।
जोड़ा लेखक Alex Pritchard, स्रोत
अब तक की प्रतिक्रिया के लिए धन्यवाद। मैंने एक पूर्ण कोड उदाहरण जोड़ा जो समस्या का प्रदर्शन करता है।
जोड़ा लेखक Alex Pritchard, स्रोत
आप एक नया जेएलएबल क्यों बना रहे हैं। बस label.setIcon (नया ImageIcon ()) का उपयोग करें; । एक आसान विकल्प मौजूद होने पर दृश्यमान जीयूआई पर घटकों को जोड़ने/हटाने से बचें।
जोड़ा लेखक camickr, स्रोत

3 उत्तर

शायद इसे आजमाएं ...

imagePanel.updateUI();
1
जोड़ा
दुर्भाग्यवश यह मेरे लिए काम नहीं कर रहा है।
जोड़ा लेखक Alex Pritchard, स्रोत
-1, updateUI() का उपयोग करने की कोई आवश्यकता नहीं है। विधि को एलएएफ परिवर्तन पर स्विंग द्वारा उपयोग किया जाता है।
जोड़ा लेखक camickr, स्रोत
किसी भी मामले में किसी उत्तर से अधिक टिप्पणी ..
जोड़ा लेखक Andrew Thompson, स्रोत

उस उद्देश्य के लिए अगली चाल का प्रयोग करें:

private void addImage(final String image){
    imagePanel.addImage(image);
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            final JScrollBar vScroll = imageScrollPane.getVerticalScrollBar();
            vScroll.setValue(vScroll.getMaximum());
        }
    });
}

उस स्थिति में सभी घटकों को जोड़ा, मान्य और चित्रित किया जाएगा, और फिर invokeLater में आप JScrollBar की स्थिति बदल सकते हैं। यह आपकी मदद करता है।

1
जोड़ा
ऐसा लगता है कि यह निश्चित रूप से काम करना चाहिए, लेकिन उस समय भी मैं गलत ऊंचाई देख रहा हूं कि vScroll.getMaxmimum() निष्पादित किया गया है।
जोड़ा लेखक Alex Pritchard, स्रोत
धन्यवाद, एलेक्स 2410, यह मेरी समस्या होने के समाप्त हो गया!
जोड़ा लेखक Alex Pritchard, स्रोत
JFrame की revalidate() विधि को कॉल करें जिसमें आप अपना JScrollPane दिखाते हैं, यह पैनल के आकार को पुन: गणना करता है।
जोड़ा लेखक alex2410, स्रोत

@ alex2410 ने एक समाधान की पहचान की - युक्त जेएफआरएएम पर revalidate() को कॉल करके, मेरे घटक आकारों की सही गणना की गई जब मुझे उनकी आवश्यकता थी। मैं addImageOuter विधि को निम्नानुसार बदलकर अपना नमूना कोड ठीक करने में सक्षम था:

    private void addImageOuter(final String image){
        final JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(this);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                imagePanel.addImageInner(image);
                frame.revalidate();
                final JScrollBar vScroll = imageScrollPane.getVerticalScrollBar();
                vScroll.setValue(vScroll.getMaximum());
            }
        });
    }
0
जोड़ा