Как добавить изображение в JPanel?
У меня есть JPanel, к которому я хотел бы добавить изображения JPEG и PNG, которые я генерирую на лету.
Все примеры, которые я видел до сих пор в Swing Tutorials, особенно в Примеры качелей используйте ImageIcon
s.
Я генерирую эти изображения в виде массивов байтов, и они обычно больше, чем обычный значок, который они используют в примерах, на 640x480.
- Есть ли какая-либо проблема (производительности или другой) при использовании класса ImageIcon для отображения изображения такого размера в JPanel?
- Какой обычный способ сделать это?
- Как добавить изображение в JPanel без использования класса ImageIcon?
Изменить. Более внимательное изучение учебников и API показывает, что вы не можете добавить ImageIcon прямо в JPanel. Вместо этого они достигают такого же эффекта, устанавливая изображение как значок JLabel. Это просто не кажется правильным...
Ответы
Ответ 1
Вот как я это делаю (немного больше информации о том, как загрузить изображение):
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
}
}
Ответ 2
Если вы используете JPanels, то, вероятно, работают с Swing. Попробуйте следующее:
BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);
Теперь изображение представляет собой компонент качания. Он становится объектом условий компоновки, как и любой другой компонент.
Ответ 3
Я думаю, что нет необходимости в подклассе чего-либо. Просто используйте Jlabel. Вы можете установить изображение в Jlabel. Итак, измените размер Jlabel, затем заполните его изображением. Все нормально. Так я и поступаю.
Ответ 4
Фред Хаслам отлично работает. У меня были проблемы с файловой дорогой, хотя, поскольку я хочу ссылаться на изображение в моей банке. Для этого я использовал:
BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));
Поскольку у меня есть только конечное число (около 10) изображений, которые мне нужно загрузить с использованием этого метода, он работает очень хорошо. Он получает файл без необходимости иметь правильный относительный путь к файлу.
Ответ 5
Вы можете полностью отказаться от собственного подкласса Component, используя класс JXImagePanel из бесплатных библиотек SwingX.
Download
Ответ 6
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
Ответ 7
- Не должно быть никаких проблем (кроме любых общих проблем, которые могут возникнуть с очень большими изображениями).
- Если вы говорите о добавлении нескольких изображений в одну панель, я бы использовал
ImageIcon
s. Для одного изображения я бы подумал о создании пользовательского подкласса JPanel
и переопределения его метода paintComponent
для рисования изображения.
- (см. 2)
Ответ 8
Вы можете подклассировать 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); }
}
Ответ 9
JPanel
почти всегда является неправильным классом для подкласса. Почему бы вам не подкласс JComponent
?
Есть небольшая проблема с ImageIcon
в том, что конструктор блокирует чтение изображения. Не проблема при загрузке из приложения, но может быть, если вы потенциально читаете сетевое соединение. Там много примеров AWT-времени использования MediaTracker
, ImageObserver
и друзей, даже в демонстрациях JDK.
Ответ 10
Я делаю что-то очень похожее в частном проекте, над которым я работаю. До сих пор я сгенерировал изображения до 1024x1024 без каких-либо проблем (кроме памяти) и может отображать их очень быстро и без каких-либо проблем с производительностью.
Переопределение метода рисования подкласса JPanel является излишним и требует больше работы, чем вам нужно.
Как я это делаю:
Class MapIcon implements Icon {...}
ИЛИ
Class MapIcon extends ImageIcon {...}
Код, который вы используете для создания изображения, будет в этом классе. Я использую BufferedImage для рисования, а затем, когда вызывается paintIcon(), используйте g.drawImvge(bufferedImage); Это уменьшает количество мигания, выполняемое во время создания изображений, и вы можете его нарезать.
Далее я расширяю JLabel:
Class MapLabel extends Scrollable, MouseMotionListener {...}
Это потому, что я хочу поместить свое изображение в панель прокрутки, I.e. отобразите часть изображения и попросите пользователя прокрутить по мере необходимости.
Итак, я использую JScrollPane для хранения MapLabel, который содержит только MapIcon.
MapIcon map = new MapIcon ();
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport ().add (mapLabel);
Но для вашего сценария (просто показывайте все изображение каждый раз). Вам необходимо добавить MapLabel в верхнюю часть JPanel и убедиться, что все они будут отображаться до полного размера изображения (путем переопределения GetPreferredSize()).
Ответ 11
Этот ответ является дополнением к ответу @shawalli...
Мне тоже хотелось ссылаться на изображение в моей баночке, но вместо того, чтобы иметь BufferedImage, я просто сделал это:
JPanel jPanel = new JPanel();
jPanel.add(new JLabel(new ImageIcon(getClass().getClassLoader().getResource("resource/images/polygon.jpg"))));
Ответ 12
Создайте исходную папку в каталоге проекта, в этом случае я назвал ее "Изображения".
JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(100, 200, 800, 800);
snakeFrame.setVisible(true);
snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
snakeFrame.pack();