2011-12-06 38 views
3

让我来解释一下我正在创建的项目。我需要一个图像列表,比如一个电影胶片,我可以将这个图像从这个带子拖到这个程序的另一个部分,然后用它做一些事情。这是最终的目标,但是现在我正在努力工作。我创建了一个存储图像信息并显示图像缩略图的FilmStripItem。我正在尝试创建一个FilmStripPanel,它是一个JScrollPane,它以Y轴形式显示每个缩略图。如何让我的图像面板不会在JScrollPane中变形和扭曲

现在我是Java Swing的新手了,我一直在试图弄清楚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); 
    } 
} 

我已经一遍又一遍地用Google搜索这再次,但似乎无法推测出来为我确切的问题。我确定这里有一些冗余的代码,并且可以随意指出。我可以使用你们可以提供的所有帮助以及任何批评,我正在尝试学习Java Swing,并且失败。

+0

有趣的问题+1 – mKorbel

+0

请看看编辑给我的职务与可运行的代码示例。这真的是最简单的,我认为这是最好的方式。 –

+0

[只在必要时在FlowLayout中显示滚动条]中有一些相关建议(http://stackoverflow.com/questions/8141035/show-scrollbars-in-flowlayout-only-when-necessary)。 – trashgod

回答

2

将滚动窗格想象为显示其内容的视图。默认情况下,根据布局,无论您放入滚动窗格,都不会真正知道它应该是多大。所以它问它的父母应该是多大,父母说:“好吧,我是这么大,所以就这么大吧。”如果你想确保使用滚动条,你必须在滚动窗格中的项目上设置一个大小。

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

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

+0

我在FilmStripItem中做了覆盖。感谢您的解释,它使这更容易理解! – Genzume

4

为了简单起见,我会自己显示ImageIcons的JList。

编辑:你可以有一个Map来把小图像映射到大图像(如果大图像不足以让你用完内存),然后使用ListSelectionListener添加到JList获取小图标,然后获取大图。大的可以显示在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(); 
     } 
     }); 
    } 
} 
+0

一旦基本功能正常运行,我会对此进行调查。谢谢你的提示。 – Genzume

+0

这就是我的方式+1 – mKorbel

+0

@Tyler:不客气。再次,请运行代码示例以查看我的意思。关键是让JList为你做所有的辛苦工作。 –