Java 如何在JScrollPane中防止图像面板挤压和扭曲

Java 如何在JScrollPane中防止图像面板挤压和扭曲,java,swing,awt,Java,Swing,Awt,让我解释一下我正在创建的项目。我需要一个图像列表,比如一个电影带,在那里我可以把图像从电影带拖到程序的另一部分,然后用它做一些事情。这是最终的目标,然而现在我只是在努力向上。我创建了一个FilmStripItem,它存储图像信息并显示图像的缩略图。我试图创建一个FilmStripPanel,它是一个JScrollPane,以Y轴的形式显示每个缩略图 现在我刚接触JavaSwing,几个星期来我一直在努力找出BorderLayout、BoxLayout、GridLayout以及哪一个是最好的。除此

让我解释一下我正在创建的项目。我需要一个图像列表,比如一个电影带,在那里我可以把图像从电影带拖到程序的另一部分,然后用它做一些事情。这是最终的目标,然而现在我只是在努力向上。我创建了一个FilmStripItem,它存储图像信息并显示图像的缩略图。我试图创建一个FilmStripPanel,它是一个JScrollPane,以Y轴的形式显示每个缩略图

现在我刚接触JavaSwing,几个星期来我一直在努力找出BorderLayout、BoxLayout、GridLayout以及哪一个是最好的。除此之外,我似乎无法让他们中的任何人按照我想要的方式工作。下面是我正在使用的代码(我去掉了类中不必要的细节)。基本上,当我运行FilmStripPanel时,它会挤压所有图像以适应窗口大小,而不会显示滚动条。如何让它显示图像(80x80)而不挤压图像

FilmStripItem.java

//Removed import info to save space

public class FilmStripItem extends JPanel {
    private BufferedImage testImg;
    private Image thumbnail;

    public FilmStripItem(BufferedImage img) {
        this.testImg = img;
        this.thumbnail = img.getScaledInstance(80, 80, Image.SCALE_SMOOTH);

        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.setMinimumSize(new Dimension(80, 80));
        add(p);
    }

    public Image GetThumbnail() {
        return this.thumbnail;
    }

    @Override
    public void paintComponent(Graphics g) {
        g.drawImage(this.thumbnail, 0, 0, null);
    }

    public static void main(String[] ARGS) {
        try {
            //Removed look and layout info
        } catch (Exception ex) {
            Logger.getLogger("Demo").log(Level.WARNING,
                    "loading CuiLookAndFeel failed", ex);
        }
        JFrame f = new JFrame("FilmStripItem");
        final FilmStripItem fi = new FilmStripItem();
        f.setContentPane(fi);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setBounds(10, 10, 128, 128);
        f.setVisible(true);
    }
}
FilmStripPanel.java

//import info removed to save space

public class FilmStripPanel extends JPanel {
    private static final int ITEM_COUNT = 15;
    private ArrayList<FilmStripItem> filmItems;

    public FilmStripPanel() {
        JPanel p = new JPanel(new GridLayout(0, 1));
        setLayout(new GridLayout(1, 1));

        filmItems = new ArrayList<FilmStripItem>();
        JComponent[] c = new JComponent[ITEM_COUNT];

        for (int i = 0; i < ITEM_COUNT; i++) {
            FilmStripItem item = new FilmStripItem();
            filmItems.add(item);
            c[i] = item;
            p.add(c[i]);
        }

        JScrollPane sp = new JScrollPane(p, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        add(sp);
    }

    public static void main(String[] args) {
        try {
            //Removed look and feel info
        } catch (Exception ex) {
            Logger.getLogger("Demo").log(Level.WARNING,
                    "loading CuiLookAndFeel failed", ex);
        }
        JFrame f = new JFrame("FilmStrip");
        final FilmStripPanel p = new FilmStripPanel();
        f.setContentPane(p);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setBounds(10, 10, 128, 512);
        f.setVisible(true);
    }
}
//删除导入信息以节省空间
公共类FilmStripPanel扩展了JPanel{
私有静态最终整数项目计数=15;
私人ArrayList电影项目;
公众谘询委员会({
JPanel p=新的JPanel(新的网格布局(0,1));
setLayout(新的GridLayout(1,1));
filmItems=newarraylist();
JComponent[]c=新的JComponent[项目计数];
对于(int i=0;i

我在谷歌上搜索了一遍又一遍,但似乎无法找到我的确切问题。我确信这里有一些多余的代码,请随意指出。我可以利用你们提供的所有帮助和任何批评,我正在努力学习Java Swing for work,但我失败了。

将滚动窗格想象为显示其内容的视图。默认情况下,根据布局的不同,您在滚动窗格中输入的内容实际上不知道应该是什么大小。所以它问它的父母它应该有多大,父母说:“好吧,我有这么大,所以也要这么大。”。如果要确保使用滚动条,必须在滚动窗格内的项目上设置大小

我的建议是:创建一个新类,扩展
JPanel
,作为滚动窗格的内容(而不是
p
)。在其中,覆盖
getPreferredSize()
并计算面板中所有图像所需的高度,并将其作为高度返回。返回任意1个图像的最大宽度作为宽度


有关滚动窗格的更多详细信息,请参阅。

为了方便起见,我会自己显示一个图像图标列表

编辑:您可以使用一个映射将小图像映射到大图像(如果大图像没有大到让您耗尽内存),然后使用添加到JList的a ListSelectionListener获取小图标,然后使用映射获取大图标。然后,可以在JLabel中显示较大的标签

例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * Source of images: Wikimedia Commons
 * http://commons.wikimedia.org/wiki/Category:Small-sized_coats_of_arms
 * @author Pete
 *
 */
@SuppressWarnings("serial")
public class FilmStripEg extends JPanel {
   public static final String WIKIMEDIA_PATH = "http://upload.wikimedia.org/" +
        "wikipedia/commons/thumb/";
   public static final String WIKIMEDIA_COMMONS_PATH = "http://upload.wikimedia.org/" +
        "wikipedia/commons/";
   public static final String[] IMAGE_PATHS = {
         "d/d8/Amriswil.jpg/98px-Amriswil.jpg",
         "e/e3/Brot-plamboz.png/102px-Brot-plamboz.png",
         "e/ef/Cerneux-pequignot.png/103px-Cerneux-pequignot.png",
         "b/b6/Cham_zg.jpg/90px-Cham_zg.jpg",
         "1/13/Chaux-du-milieu.png/102px-Chaux-du-milieu.png",
         "c/c2/Diessenhofen.GIF/99px-Diessenhofen.GIF",
         "f/f0/Cressier.gif/100px-Cressier.gif",
         "8/8c/GW-GL-Glarus_Sued.png/100px-GW-GL-Glarus_Sued.png",
         "3/3d/GW-GL-Haetzingen.png/100px-GW-GL-Haetzingen.png",
         "d/de/GW-GR-Tomils.png/100px-GW-GR-Tomils.png",
         "e/e5/Montmollin.png/101px-Montmollin.png", 
         "7/73/GW-GL-Naefels.gif/100px-GW-GL-Naefels.gif",
         "3/3d/GW-NE-Val-de-Travers.png/104px-GW-NE-Val-de-Travers.png",
         "d/d9/Herdern.gif/102px-Herdern.gif",
         "3/35/Kesswil.GIF.gif/101px-Kesswil.GIF.gif",
         "0/00/Roche-vaud.jpg/105px-Roche-vaud.jpg",
         "d/da/S-blaise.png/107px-S-blaise.png", 
         "3/3d/Vaugondr.jpg/107px-Vaugondr.jpg"};

   private static final int PREF_W = 600;
   private static final int PREF_H = PREF_W;

   private DefaultListModel model = new DefaultListModel();
   private JList filmStripList = new JList(model);
   private JLabel imageLabel = new JLabel();
   private Map<ImageIcon, ImageIcon> iconMap = new HashMap<ImageIcon, ImageIcon>();

   public FilmStripEg() {
      JPanel centerPanel = new JPanel(new GridBagLayout());
      centerPanel.add(imageLabel);
      centerPanel.setBackground(Color.white);

      setLayout(new BorderLayout());
      add(new JScrollPane(filmStripList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.LINE_END);
      add(centerPanel, BorderLayout.CENTER);
      try {
         for (String smallImagePath : IMAGE_PATHS) {
            BufferedImage img = ImageIO.read(new URL(WIKIMEDIA_PATH + smallImagePath));
            ImageIcon smallIcon = new ImageIcon(img);
            model.addElement(smallIcon);

            String largeImagePath = WIKIMEDIA_COMMONS_PATH + smallImagePath.replaceAll("/\\d{1,3}px.*", "");
            BufferedImage largeImg = ImageIO.read(new URL(largeImagePath));
            ImageIcon largeIcon = new ImageIcon(largeImg);

            iconMap.put(smallIcon, largeIcon);
         }
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }

      filmStripList.addListSelectionListener(new ListSelectionListener() {
         public void valueChanged(ListSelectionEvent e) {
            if (e.getValueIsAdjusting()) {
               return;
            }
            ImageIcon icon = iconMap.get(filmStripList.getSelectedValue());
            imageLabel.setIcon(icon);
         }
      });

   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      FilmStripEg mainPanel = new FilmStripEg();

      JFrame frame = new JFrame("FilmStripEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.GridBagLayout;
导入java.awt.image.buffereImage;
导入java.io.IOException;
导入java.net.MalformedURLException;
导入java.net.URL;
导入java.util.HashMap;
导入java.util.Map;
导入javax.imageio.imageio;
导入javax.swing.*;
导入javax.swing.event.ListSelectionEvent;
导入javax.swing.event.ListSelectionListener;
/**
*图片来源:Wikimedia Commons
* http://commons.wikimedia.org/wiki/Category:Small-上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装上装
*@作者皮特
*
*/
@抑制警告(“串行”)
公共级电影带扩展JPanel{
公共静态最终字符串WIKIMEDIA_PATH=”http://upload.wikimedia.org/" +
“wikipedia/commons/thumb/”;
公共静态最终字符串WIKIMEDIA_COMMONS_PATH=”http://upload.wikimedia.org/" +
“wikipedia/commons/”;
公共静态最终字符串[]图像路径={
“d/d8/Amriswil.jpg/98px Amriswil.jpg”,
“e/e3/Brot plamboz.png/102px Brot plamboz.png”,
“e/ef/Cerneux pequignot.png/103px Cerneux pequignot.png”,
“b/b6/Cham_zg.jpg/90px-Cham_zg.jpg”,
“1/13/Chaux du milieu.png/102px Chaux du milieu.png”,
“c/c2/Diessenhofen.GIF/99px Diessenhofen.GIF”,
“f/f0/Cressier.gif/100px Cressier.gif”,
“8/8c/GW-GL-Glarus_suited.png/100px-GW-GL-Glarus_suited.png”,
“3/3d/GW GL Haetzingen.png/100px GW GL Haetzingen.png”,
“d/de/GW GR Tomils.png/100px GW GR Tomils.png”,
“e/e5/Montmollin.png/101px Montmollin.png”,
“7/73/GW GL Naefels.gif/100px GW GL Naefels.gif”,
“3/3d/GW NE Val de Travers.png/104px GW NE Val de Travers.png”,
“d/d9/Herdern.gif/102px Herdern.gif”,
“3/35/Kesswil.GIF.GIF/101px Kesswil.GIF.GIF”,
“0/00/Roche vaud.jpg/105px Roche vaud.jpg”,
“d/da/S-blaise.png/107px-S-blaise.png”,
“3/3d/Vaugondr.jpg/107px Vaugondr.jpg”};
专用静态最终整型预调W=600;
私有静态final int PREF_H=PREF_W;
私有DefaultListModel模型=新定义