У меня есть JPanel, к которому я хотел бы добавить изображения JPEG и PNG, которые я генерирую на лету.
Все примеры, которые я видел в учебниках по Swing , особенно в примерах Swing, используют ImageIcon
s.
Я генерирую эти изображения как байтовые массивы, и они обычно больше, чем общий значок, который они используют в примерах, в 640x480.
- Есть ли какая-либо (производительность или другая) проблема в использовании класса ImageIcon для отображения изображения такого размера в JPanel?
- Какой обычный способ это сделать?
- Как добавить изображение в JPanel без использования класса ImageIcon?
Изменить : более тщательное изучение учебников и API показывает, что вы не можете добавить ImageIcon непосредственно в JPanel. Вместо этого они достигают того же эффекта, устанавливая изображение в виде значка JLabel. Это просто не правильно ...
MemoryImageSource
чем конвертировать их в формат JPEG или PNG, а затем читать,ImageIO
как предлагает большинство ответов. Вы можете получитьImage
изMemoryImageSource
созданного с вашим данными изображения, используяcreateImage
, и отобразить, как предложено в одном из ответов.Ответы:
Вот как я это делаю (немного больше информации о том, как загрузить изображение):
источник
Principle of Encapsulation
методы в то время как подмену Высшего класса, доступ Тендерный изpaintComponent(...)
метода являетсяprotected
и неpublic
:-)Principle of Encapsulation
. Просто помните, что при программировании то, что должно быть скрыто от остальной части кода, должно сохраняться таким образом, вместо того, чтобы быть видимым для всего в коде. Похоже, что это одна такая вещь, которая приходит с опытом, как каждый учится каждый день. Любая книга может дать базовое представление о том, что такое инкапсуляция, но именно то, как мы реализуем наш код, определяет, насколько мы придерживаемся этой концепции.Если вы используете JPanels, то, вероятно, работаете с Swing. Попробуй это:
Изображение теперь является компонентом свинга. Это становится предметом условий макета, как и любой другой компонент.
источник
Путь Фреда Хаслама работает отлично. У меня возникли проблемы с путем к файлу, так как я хочу сослаться на изображение в моем банке. Для этого я использовал:
Поскольку у меня есть только конечное число (около 10) изображений, которые мне нужно загрузить с помощью этого метода, он работает довольно хорошо. Он получает файл без необходимости иметь правильный относительный путь к файлу.
источник
BufferedImage previewImage = ImageIO.read(new URL(imageURL));
чтобы получить мои изображения с сервера.Я думаю, что нет необходимости в подклассе чего-либо. Просто используйте Jlabel. Вы можете установить изображение в Jlabel. Итак, измените размер Jlabel, затем заполните его изображением. Все нормально. Это способ, которым я делаю.
источник
Вы можете избежать полного развертывания собственного подкласса Component, используя класс JXImagePanel из бесплатных библиотек SwingX .
Скачать
источник
источник
Вы можете создать подкласс JPanel - вот выдержка из моей ImagePanel, которая помещает изображение в любое из 5 мест: верхнее / левое, верхнее / правое, среднее / среднее, нижнее / левое или нижнее / правое:
источник
ImageIcon
s. Для одного изображения я бы подумал о создании собственного подклассаJPanel
и переопределении егоpaintComponent
метода для рисования изображения.источник
JPanel
почти всегда неправильный класс для подкласса. Почему бы вам не подклассJComponent
?Существует небольшая проблема
ImageIcon
в том, что конструктор блокирует чтение изображения. Не проблема при загрузке из jar приложения, но, возможно, если вы читаете по сетевому соединению. Там множество примеров AWT эпохи использованияMediaTracker
,ImageObserver
и друзей, даже в демо - версии JDK.источник
Я делаю нечто очень похожее в частном проекте, над которым я работаю. До сих пор я генерировал изображения размером до 1024x1024 без каких-либо проблем (кроме памяти) и могу отображать их очень быстро и без проблем с производительностью.
Переопределение метода рисования подкласса JPanel является излишним и требует больше работы, чем нужно.
Я делаю это так:
ИЛИ
Код, который вы используете для создания изображения, будет в этом классе. Я использую BufferedImage, чтобы рисовать тогда, когда вызывается paintIcon (), используйте g.drawImvge (bufferedImage); Это уменьшает количество перепрошивок, которые вы выполняете во время создания изображений, и вы можете их обработать.
Далее я расширяю JLabel:
Это потому, что я хочу поместить свое изображение в область прокрутки, то есть отобразить часть изображения и заставить пользователя прокручивать его по мере необходимости.
Затем я использую JScrollPane для хранения MapLabel, который содержит только MapIcon.
Но для вашего сценария (просто показывайте все изображение каждый раз). Вам необходимо добавить MapLabel в верхнюю JPanel и убедиться, что все их размеры соответствуют полному размеру изображения (переопределяя GetPreferredSize ()).
источник
Создайте исходную папку в каталоге вашего проекта, в данном случае я назвал ее Images.
источник
Вы можете избежать использования собственной
Component
библиотеки s и SwingX иImageIO
класса:источник
Этот ответ является дополнением к ответу @ shawalli ...
Я тоже хотел сослаться на изображение внутри моей банки, но вместо BufferedImage я просто сделал это:
источник
Я вижу много ответов, на самом деле не обращаясь к трем вопросам ОП.
1) Слово о производительности: байтовые массивы, вероятно, неэффективны, если вы не можете использовать точный порядок байтов в пикселях, который соответствует вашим адаптерам дисплея, текущему разрешению и глубине цвета.
Чтобы добиться максимальной производительности при рисовании, просто преобразуйте изображение в BufferedImage, созданный с типом, соответствующим вашей текущей графической конфигурации. См. CreateCompatibleImage на https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
Эти изображения будут автоматически кэшироваться в памяти видеокарты после рисования несколько раз без каких-либо усилий по программированию (это стандартно в Swing начиная с Java 6), и, следовательно, фактическое рисование займет незначительное количество времени - если вы не изменили изображение ,
Изменение изображения будет сопровождаться дополнительной передачей памяти между основной памятью и памятью GPU, что является медленным. Избегайте «перерисовки» изображения в BufferedImage, поэтому избегайте использования getPixel и setPixel во всех отношениях.
Например, если вы разрабатываете игру, вместо того, чтобы рисовать всех игровых акторов в BufferedImage, а затем в JPanel, гораздо быстрее загружать всех акторов как меньшие BufferedImages и рисовать их по одному в вашем коде JPanel в их правильное положение - таким образом, нет никакой дополнительной передачи данных между основной памятью и памятью GPU, кроме начальной передачи изображений для кэширования.
ImageIcon будет использовать BufferedImage под капотом - но в основном распределение BufferedImage с правильным графическим режимом является ключевым, и нет никаких усилий, чтобы сделать это правильно.
2) Обычный способ сделать это - нарисовать BufferedImage в переопределенном методе paintComponent в JPanel. Хотя Java поддерживает большое количество дополнительных полезных функций, таких как цепочки буферов, управляющие VolatileImages, кешируемыми в памяти графического процессора, нет необходимости использовать ни один из них, так как Java 6 работает достаточно хорошо, не раскрывая всех этих деталей ускорения графического процессора.
Обратите внимание, что ускорение графического процессора может не работать для определенных операций, таких как растяжение полупрозрачных изображений.
3) Не добавляйте. Просто нарисуйте, как указано выше:
«Добавление» имеет смысл, если изображение является частью макета. Если вам нужно это как фоновое или переднее изображение, заполняющее JPanel, просто нарисуйте paintComponent. Если вы предпочитаете создавать универсальный компонент Swing, который может отображать ваше изображение, то это та же история (вы можете использовать JComponent и переопределить его метод paintComponent), а затем добавить его в свой макет компонентов GUI.
4) Как преобразовать массив в Bufferedimage
Преобразование ваших байтовых массивов в PNG, а затем их загрузка довольно ресурсоемки. Лучший способ - преобразовать существующий байтовый массив в BufferedImage.
Для этого: не используйте петли и не копируйте пиксели. Это очень, очень медленно. Вместо:
источник