Barry Staes
Barry Staes

Reputation: 4115

Java swing component to show image grid

Its been a while since i built a desktop JAVA application.. after lots of documentation and doing implementation tests, i still have not found an image grid solution.

Either Java lacks such a ready-to-use component (?!) or you tell me to brush up my google-fu. :)

I have a very simple technical premises: a JDialog that allows the user to pick an image. Input is a Map<Integer, String> list that holds filenames. Output is the Integer key the user chose. GUI also is simple: user chooses 1 image using mouse or keyboard, and dialog closes. All images are 80x80px and loaded from filename, not a resource.

I tried several approaches so far this morning:

In lieu of your answer, i am now working on the latter, which should work but i cant believe everyone needs to reinvent the same GUI wheel here. How to have the user select an image from my Map<Integer, String>? Are there JAVA libraries/widgets/components that i should look to avoid this?

I hope this isn't being modded down, i have no working implementation with error to show you guys.. this question is about how/where to find the components or what approaches would be better. Its 2014 and i cant believe that JAVA still requires me to build my own "GUI component" just to see some images.. not even Delphi or Mono does that.

Upvotes: 0

Views: 1740

Answers (2)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

If all you want is a grid of images, and having them selectable, consider using a JList, filling it with appropriate ImageIcons, and giving it a ListSelectionListener. In the Listener you can close the enclosing dialog when a selection has been made.

You state:

Try and implement myJList.setModel(), but i cant get it to just take my Map<> and show thumbnails. (overcomplicates!)

You need to use your Map to populate your ListModel, and set that Model to the JList's model.

For example:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

@SuppressWarnings("serial")
public class ImageGridPanel extends JPanel {
   public static final String PATH = "http://images-2.drive.com.au/2011/";
   public static final String[] CARS = {
         "04/15/2308961/giulietta_1024-80x80.jpg",
         "11/18/2781958/audi-a1-sportback_600-80x80.jpg",
         "12/23/2856762/fiat-500-80x80.jpg",
         "01/12/2129944/Honda-Civic-Sedan-concept-1_600-80x80.jpg",
         "12/23/2856581/mini-roadster-80x80.jpg",
         "12/23/2856571/hyundai-veloster-80x80.jpg",
         "12/23/2856771/hyundai-i30-80x80.jpg",
         "12/23/2856580/mini-coupe-80x80.jpg" };

   private DefaultListModel<Car> carModel = new DefaultListModel<>();
   final JTextField textField = new JTextField(20);

   public ImageGridPanel() {
      for (String carPath : CARS) {
         String path = PATH + carPath;
         try {
            URL imgUrl = new URL(path);
            BufferedImage img = ImageIO.read(imgUrl);
            ImageIcon icon = new ImageIcon(img);
            String name = carPath.substring(carPath.lastIndexOf("/"));
            name = name.substring(1, name.lastIndexOf("-"));
            carModel.addElement(new Car(name, icon));
         } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
         }
      }

      ShowGridAction showAction = new ShowGridAction("Car Grid", carModel);
      JButton showGridBtn = new JButton(showAction);
      add(showGridBtn);
      add(textField);
   }

   private class ShowGridAction extends AbstractAction {
      private CarGridPanel carGridPanel;

      public ShowGridAction(String name, DefaultListModel<Car> carModel) {
         super(name);
         carGridPanel = new CarGridPanel(carModel);
      }

      public CarGridPanel getCarGridPanel() {
         return carGridPanel;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         Window win = SwingUtilities.getWindowAncestor((Component) e.getSource());
         JDialog dialog = new JDialog(win, "Cars", ModalityType.APPLICATION_MODAL);
         dialog.add(carGridPanel);
         dialog.pack();
         dialog.setLocationRelativeTo(null);
         int x = dialog.getLocation().x;
         int y = dialog.getLocation().y - 150;               
         dialog.setLocation(x, y);
         dialog.setVisible(true);

         Car selectedCar = carGridPanel.getSelectedCar();
         if (selectedCar != null) {
            textField.setText(selectedCar.getName());
         }

      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("ImageGrid");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new ImageGridPanel());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}



class Car {
   String name;
   Icon icon;

   public Car(String name, Icon icon) {
      this.name = name;
      this.icon = icon;
   }

   public String getName() {
      return name;
   }

   public Icon getIcon() {
      return icon;
   }

}

@SuppressWarnings("serial")
class CarGridPanel extends JPanel {
   private JList<Car> carList = new JList<>();
   private Car selectedCar;

   public CarGridPanel(ListModel<Car> model) {
      carList.setModel(model);
      carList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
      carList.setVisibleRowCount(2);
      carList.setCellRenderer(new DefaultListCellRenderer() {
         @Override
         public Component getListCellRendererComponent(JList<?> list,
               Object value, int index, boolean isSelected, boolean cellHasFocus) {
            if (value != null) {
               Car carValue = (Car) value;
               value = carValue.getIcon();
            } else {
               value = "";
            }
            return super.getListCellRendererComponent(list, value, index,
                  isSelected, cellHasFocus);
         }
      });
      setLayout(new BorderLayout());
      add(new JScrollPane(carList));

      carList.addListSelectionListener(new ListListener());
   }

   public Car getSelectedCar() {
      return selectedCar;
   }

   private class ListListener implements ListSelectionListener {

      @Override
      public void valueChanged(ListSelectionEvent e) {
         selectedCar = carList.getSelectedValue();

         Window win = SwingUtilities.getWindowAncestor(CarGridPanel.this);
         win.dispose();
      }

   }
}

Upvotes: 4

arcy
arcy

Reputation: 13123

No, Java doesn't have what you want.

Java is a general-purpose programming language, not a toolset, particularly not a specialized desktop GUI toolset. This is not a denigration of the language, just a statement of a purpose that it was not developed to fulfill.

If Delphi or Mono or anything has your particular widget, then I suggest you program in that, instead. This is not a denigration of you, just an observation that, if you do not want to put together the widget you want from lower-level components and code, then Java is not the right language/tool for you to use to do it.

As for not believing that Java "still requires" you to build your own component, I can only say that you don't get to choose which languages provide which features. I'm just as glad Java isn't littered with your component and the hundreds of others that people like you would come up with that they think Java should provide. It's big enough as it is.

Upvotes: 1

Related Questions