Как добавить изображение в JPanel? - PullRequest
328 голосов
/ 18 ноября 2008

У меня есть JPanel , к которому я хотел бы добавить изображения JPEG и PNG, которые я генерирую на лету.

Все примеры, которые я видел до сих пор в Swing Tutorials , особенно в Swing, use ImageIcon s.

Я генерирую эти изображения в виде байтовых массивов, и они обычно больше, чем общий значок, который они используют в примерах, в 640x480.

  1. Есть ли какая-либо (производительность или другая) проблема в использовании класса ImageIcon для отображения изображения такого размера в JPanel?
  2. Каков обычный способ сделать это?
  3. Как добавить изображение в JPanel без использования класса ImageIcon?

Редактировать : Более тщательное изучение учебников и API показывает, что вы не можете добавить ImageIcon непосредственно в JPanel. Вместо этого они достигают того же эффекта, устанавливая изображение в виде значка JLabel. Это просто нехорошо ...

Ответы [ 14 ]

507 голосов
/ 25 апреля 2010

Если вы используете JPanels, то, вероятно, работаете с Swing. Попробуйте это:

BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);

Изображение теперь является компонентом свинга. Он становится объектом условий макета, как и любой другой компонент.

242 голосов
/ 18 ноября 2008

Вот как я это делаю (немного больше информации о том, как загрузить изображение):

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ImagePanel extends JPanel{

    private BufferedImage image;

    public ImagePanel() {
       try {                
          image = ImageIO.read(new File("image name and path"));
       } catch (IOException ex) {
            // handle exception...
       }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters            
    }

}
33 голосов
/ 27 декабря 2010

Путь Фреда Хаслама работает отлично. У меня возникли проблемы с путем к файлу, так как я хочу сослаться на изображение в моем банке. Для этого я использовал:

BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));

Поскольку у меня есть только конечное число (около 10) изображений, которые мне нужно загрузить с помощью этого метода, он работает довольно хорошо. Он получает файл без правильного относительного пути к файлу.

32 голосов
/ 03 октября 2009

Я думаю, что нет необходимости создавать подклассы для чего-либо. Просто используйте Jlabel. Вы можете установить изображение в Jlabel. Итак, измените размер Jlabel, затем заполните его изображением. Все нормально. Это способ, которым я делаю.

20 голосов
/ 19 ноября 2008

Вы можете полностью избежать прокручивания своего собственного подкласса Component, используя класс JXImagePanel из бесплатных библиотек SwingX .

Скачать

11 голосов
/ 05 мая 2013
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
8 голосов
/ 18 ноября 2008
  1. Не должно быть никаких проблем (кроме общих проблем, которые могут возникнуть у вас с очень большими изображениями).
  2. Если вы говорите о добавлении нескольких изображений на одну панель, я бы использовал ImageIcon s. Для одного изображения я бы подумал о создании пользовательского подкласса JPanel и переопределении его paintComponent метода для рисования изображения.
  3. (см. 2)
7 голосов
/ 18 ноября 2008

Вы можете создать подкласс JPanel - вот выдержка из моей ImagePanel, которая помещает изображение в любое из 5 мест: верхнее / левое, верхнее / правое, среднее / среднее, нижнее / левое или нижнее / правое:

protected void paintComponent(Graphics gc) {
    super.paintComponent(gc);

    Dimension                           cs=getSize();                           // component size

    gc=gc.create();
    gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
    if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2)       +mmHrzShift),(((cs.height-mmSize.height)/2)        +mmVrtShift),null); }
    if(tlImage!=null) { gc.drawImage(tlImage,(insets.left                       +tlHrzShift),(insets.top                           +tlVrtShift),null); }
    if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top                           +trVrtShift),null); }
    if(blImage!=null) { gc.drawImage(blImage,(insets.left                       +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
    if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
    }
6 голосов
/ 18 ноября 2008

Я делаю нечто очень похожее в частном проекте, над которым я работаю. До сих пор я генерировал изображения размером до 1024x1024 без каких-либо проблем (кроме памяти) и могу отображать их очень быстро и без проблем с производительностью.

Переопределение метода рисования подкласса JPanel является излишним и требует больше работы, чем нужно.

Как я это делаю:

Class MapIcon implements Icon {...}

OR

Class MapIcon extends ImageIcon {...}

Код, который вы используете для создания изображения, будет в этом классе. Я использую BufferedImage, чтобы рисовать тогда, когда вызывается paintIcon (), используйте g.drawImvge (bufferedImage); Это уменьшает количество перепрошивок, которые вы выполняете во время создания изображений, и вы можете их обработать.

Далее я расширяю JLabel:

Class MapLabel extends Scrollable, MouseMotionListener {...}

Это потому, что я хочу поместить свое изображение в область прокрутки, т.е. отобразить часть изображения и заставить пользователя прокручивать по мере необходимости.

Итак, я использую JScrollPane для хранения MapLabel, который содержит только MapIcon.

MapIcon map = new MapIcon (); 
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();

scrollPane.getViewport ().add (mapLabel);

Но для вашего сценария (просто показывайте изображение целиком каждый раз). Вам необходимо добавить MapLabel в верхнюю JPanel и убедиться, что все их размеры соответствуют полному размеру изображения (переопределив GetPreferredSize ()).

6 голосов
/ 18 ноября 2008

JPanel - почти всегда неправильный класс для подкласса. Почему бы вам не подкласс JComponent?

Существует небольшая проблема с ImageIcon в том, что конструктор блокирует чтение изображения. Не проблема при загрузке из jar приложения, но, возможно, если вы читаете по сетевому соединению. Существует множество примеров использования MediaTracker, ImageObserver и друзей эпохи AWT, даже в демонстрационных версиях JDK.

...