调用打包后滚动条不显示

时间:2012-11-02 10:49:08

标签: java swing jscrollpane bufferedimage preferredsize

我有一个包含JScrollPane的JFrame,其中包含一个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();
        }

    }

///////////////// next class ///////////////////

    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();
        }

    }

3 个答案:

答案 0 :(得分:1)

  1. 必须在屏幕上为max_size决定JFrame

  2. 添加新Image后,您必须致电revalidate&amp; repaint

  3. JPanel
  4. 然后JPanel返回正确的PreferredSize

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

  6. similair question about max size for JDialog

  7. SSCCE发布后更快获得更好的帮助,因为上午点只是关于理论的

答案 1 :(得分:0)

我的建议是:如果您想要显示图片,请不要使用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);
    }
}

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

答案 2 :(得分:0)

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

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