【问题标题】:scrollbar not showing after call to pack调用 pack 后滚动条不显示
【发布时间】:2012-11-02 10:49:07
【问题描述】:

我有一个 JFrame,其中包含一个 JScrollPane,其中包含一个 JPanel。 我在 JPanel 上上传和绘制图像。图像的大小可能会发生变化。每次我绘制一个新图像时,在一个事件之后,我都会在 JFrame 上调用 pack。 这一切都可以正常工作,JFrame 并且所有内容都正确调整了大小,但是我遇到了滚动条出现和消失的问题。如果我删除对 pack() 的调用,滚动条就在那里,但包含的 JPanel 不会调整大小。为什么 ?我能做些什么 ? 这是用于测试的修剪后的 SSCCE 代码。使用的图像位于 enter link description here

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import javax.imageio.ImageIO;
    import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JScrollPane;
    import javax.swing.JToolBar;
    import javax.swing.border.Border;

    @SuppressWarnings("serial")
    public class JComicFrame extends JFrame {
        private JComicPanel panel;
        private JToolBar toolbar;
        private JButton buttonZoom;
        private JButton buttonPrev;
        private JButton buttonNext;
        private JMenuBar menuBar;
        private JScrollPane scroller;
        private BufferedImage img;
        private ArrayList<BufferedImage> images;
        private int currentFile;
        public JComicFrame(){

            super("JComic");        

            images = new ArrayList<BufferedImage>();
            try {
                images.add(ImageIO.read(new File("1.jpg")));
                images.add(ImageIO.read(new File("2.jpg")));
                images.add(ImageIO.read(new File("3.jpg")));    
                images.add(ImageIO.read(new File("4.jpg")));    
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            BorderLayout layout = new BorderLayout();
            setLayout(layout);
            createToolbar();
            createPanel();
            createMenu();
            setJMenuBar(menuBar);
            add(toolbar,BorderLayout.NORTH);
            scroller = new JScrollPane(panel);
            add(scroller,BorderLayout.CENTER);
            setVisible(true);

            currentFile = -1;
            BufferedImage img = getNextFile();
            panel.setImage(img);

            pack();


        }

        private BufferedImage getNextFile(){
            currentFile = currentFile + 1;
            currentFile = (currentFile > images.size() - 1) ?    images.size() - 1 : currentFile;
            return images.get(currentFile);
        }

        private BufferedImage getPrevFile(){
            currentFile = currentFile - 1;
            currentFile = (currentFile < 0) ? 0 : currentFile;
            return images.get(currentFile);

        }



        private void createPanel(){
            Border raisedbevel, loweredbevel;
            raisedbevel = BorderFactory.createRaisedBevelBorder();
            loweredbevel = BorderFactory.createLoweredBevelBorder();
            panel = new JComicPanel(img);
            panel.setBorder(BorderFactory.createCompoundBorder(raisedbevel,loweredbevel));


        }
        private void createToolbar(){
            toolbar = new JToolBar();
            toolbar.setFloatable(false);
            buttonZoom = new JButton("+");
            toolbar.add(buttonZoom);

            buttonPrev = new JButton("<-");
            buttonPrev.addActionListener
            (
                    new ActionListener(){
                        public void actionPerformed(ActionEvent e){
                            BufferedImage img = getPrevFile();
                            panel.setImage(img);
                            pack();
                            repaint();



                        }
                    }
                    );
            toolbar.add(buttonPrev);
            buttonNext = new JButton("->");
            buttonNext.addActionListener
            (
                    new ActionListener(){
                        public void actionPerformed(ActionEvent e){
                            BufferedImage img = getNextFile();
                            panel.setImage(img);
                            pack();




                        }
                    }
                    );
            toolbar.add(buttonNext);
            toolbar.setBackground(Color.WHITE);


        }
        private void createMenu(){
            JMenu menuFile,menuJComic;
            JMenuItem fileOpen; 
            JMenuItem quitJComic,aboutJComic;


            menuBar = new JMenuBar();
            menuJComic = new JMenu("JComic");
            aboutJComic = new JMenuItem("About JComic...");
            menuJComic.add(aboutJComic);
            quitJComic = new JMenuItem("Quit");
            quitJComic.addActionListener(
                    new ActionListener(){
                        public void actionPerformed(ActionEvent e) {
                            System.exit(0);
                        }
                    }
                    );
            menuJComic.add(quitJComic);

            menuBar.add(menuJComic);

            menuFile = new JMenu("File");

            fileOpen = new JMenuItem("Open...");

            menuFile.add(fileOpen);
            menuBar.add(menuFile);


        }

        public static void main(String args[]){
            JComicFrame theFrame = new JComicFrame();



            theFrame.show();
        }

    }

//////////////下一节课////////////////

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.image.BufferedImage;

    import javax.swing.JPanel;





    public class JComicPanel extends JPanel{


        private static final long serialVersionUID = 1L;
        private BufferedImage img = null;
        private float scaling = 0.5f;
        private int newW, newH;


        public JComicPanel(BufferedImage img){
            super();

            this.img = img;

        }

        public JComicPanel(){
            super();
            this.img = null;

        }


        private Runnable scaleImage(BufferedImage img){
            int w = img.getWidth();
            int h = img.getHeight();
            newW = (int)(w * scaling);
            newH = (int)(h * scaling);
            BufferedImage dimg =  new BufferedImage(newW, newH, img.getType());  
            Graphics2D g = dimg.createGraphics();  
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY); 
            g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);  
            this.img = dimg;
            revalidate();
            repaint();
            return null;

        }


        public void setImage(BufferedImage img){

            Thread t = new Thread(scaleImage(img));
            t.start();
        }


        public Dimension getPreferredSize(){
            System.out.println("PS");
            if(img==null || this.isVisible() == false)  
                return new Dimension(1,1);
            else 
                return new Dimension(img.getWidth(),img.getHeight());

        }

        public void paintComponent(Graphics g){


            Graphics2D g2d = (Graphics2D)g.create();
            super.paintComponent(g);
            g2d.drawImage(img,0,0,getSize().width,getSize().height, this); 
            g2d.dispose();
        }

    }

【问题讨论】:

    标签: java swing jscrollpane bufferedimage preferredsize


    【解决方案1】:
    1. 必须在屏幕上为max_size 决定JFrame

    2. 添加新的Image 后,您必须为JPanel 调用revalidaterepaint

    3. 然后JPanel返回正确的PreferredSize

    4. 将此Dimension 与所需的JFrames max size 进行比较,如果大于则不要调用pack(),反之亦然

    5. similair question about max size for JDialog

    6. 为了获得更好的帮助,请尽快发布SSCCE,因为上午点数仅与理论有关

    【讨论】:

    • 我会尝试,即使老实说我已经尝试了所有可能的重绘、验证、重新验证、更新的组合......至于在 ActionEvent 中的调用,如果我删除它面板没有调整大小,我需要根据加载的图像动态更改它
    • 问题只有一个 BuferredIamge,JPanel 中没有放置任何其他 JComponent,图像填满整个 JPanel 区域
    【解决方案2】:

    我的建议是:如果要显示图片,不要使用JPanel,使用JLabel

    import javax.swing.*;
    
    public class ScrollPane extends JFrame{
        JLabel label = new JLabel();
        JScrollPane scrollPane = new JScrollPane();
    
        public ScrollPane(){
            label.setIcon(new ImageIcon("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/Image.jpg"));
            scrollPane.setViewportView(label);
            add(scrollPane);
        }
    
        public static void main(String[] args) {
            ScrollPane sp = new ScrollPane();
            sp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            //sp.setSize(1024,800);
            sp.pack();
            sp.setVisible(true);
        }
    }
    

    另外,不要每次在JPanel上添加图片后都调用pack();,调用repaint();方法,如果你想使用JPanel显示图片。

    【讨论】:

      【解决方案3】:

      无需每次都声明 pack()。如果您在 main 方法中声明它就足够了。这意味着不在以下部分声明:

          public void actionPerformed(ActionEvent e){
                      BufferedImage img = (BufferedImage)archiveHandler.getNextFile();
                      panel.setImage(img);
                      pack();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-24
        • 1970-01-01
        • 1970-01-01
        • 2019-11-23
        • 2012-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多