Java draw - Как да добавите изображение към JPanel CODE Решен

поставяне на изображения (13)

Виждам много отговори, да не говорим за трите въпроса на ОП.

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, кеширани в паметта на GPU, няма нужда да се използва което и да е от тях след Java 6, което върши сравнително добра работа, без да излага всички тези подробности за ускорението на GPU.

Моля, обърнете внимание, че GPU ускорението може да не работи за определени операции, като например разтягане на полупрозрачни изображения.

3) Не добавяйте. Просто го начертайте както по-горе:

„Добавянето“ има смисъл, ако изображението е част от оформлението. Ако имате нужда от него като фон или преден план, запълващ JPanel, просто paintComponent. Ако предпочитате да създадете общ Swing компонент, който може да показва вашето изображение, тогава това е същата история (можете да използвате JComponent и да замените метода paintComponent) и след това да го добавите към оформлението на GUI компонента.

4) Как да конвертирате масива в Bufferedimage

Преобразуването на вашите байтови масиви в PNG и след това зареждането им е доста ресурсоемко. Най-добре е да конвертирате съществуващ байтов масив в BufferedImage.

За да направите това: не използвайте за цикли и копия на пиксели. Много е бавно. Вместо:

  • разберете предпочитаната байтова структура на BufferedImage (в момента е безопасно да приемете RGB или RGBA, което е 4 байта на пиксел)
  • прегледайте разопаковано и разопаковано (напр. 142px широко изображение), но в реалния живот това ще се съхранява като 256 широк масивпиксели, тъй като обработва и маскира неизползваните пиксели по-бързо с GPU хардуер)
  • след това, след като създадете масив според тези принципи, методът за масив setRGB BufferedImage може да копира вашия масив в BufferedImage.

Имам JPanel, към който бих искал да добавя JPEG и PNG изображения, които генерирам в движение.

Всички примери, които съм виждал досега в ImageIcon Swing, особено примерите на Swing, използват ImageIcon.

Генерирам тези изображения като байтови масиви и те обикновено са по-големи от обикновената икона, която използват в примерите с 640x480.

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

Редактиране : По-внимателен поглед върху уроците и API разкрива, че не можете да добавите ImageIcon директно към JPanel. Вместо това те постигат същия ефект, като задават изображението като JLabel икона. Просто не ми се струва добре.

Можете да подкласирате JPanel - ето извадка от моя ImagePanel, който поставя изображение на което и да е от 5 места: горе/ляво, горе/дясно, средно/средно, долу/ляво или долу/дясно:

Този отговор е допълнение към отговора на @shawalli.

Също така исках да направя препратка към изображение в моя буркан, но вместо да имам BufferedImage, направих това:

Можете напълно да върнете назад своя собствен подклас Component, като използвате класа JXImagePanel от безплатните библиотеки на SwingX.

В този случай създайте папка източник в директорията на вашия проектКръстих го „Изображения“.

  1. Не би трябвало да има проблеми (освен общите проблеми, които може да имате с много големи изображения).
  2. Ако говорите за добавяне на множество изображения към един панел, бих използвал ImageIcon s. За едно изображение бих помислил за създаване на персонализиран подклас JPanel и замяна на неговия метод paintComponent, за да нарисува изображението.
  3. (вижте 2)

Можете да избегнете използването на собствен компонент и библиотека SwingX и клас ImageIO:

Мисля, че няма нужда да подкласирате нищо. Просто използвайте jlabel. Можете да зададете изображение в Jlabel. Така че, преоразмерете Jlabel, след което го напълнете с изображение. Всичко е наред. Така го правя.

Правя нещо много подобно по частен проект, върху който работя. Досега съм генерирал изображения до 1024x1024 без никакъв проблем (освен памет) и мога да ги показвам много бързо и без проблем с производителността.

Замяната на метода за чертане на подклас JPanel е пресилено и изисква повече работа, отколкото ви е необходима.

Начинът, по който го правя:

Кодът, който използвате за създаване на изображението, ще бъде в този клас. Използвам BufferedImage за рисуване и след това, когато се извика paintIcon(), използвам g.drawImvge(bufferedImage); Това намалява количеството мигане, извършено по време на създаване на изображение и можете да го нарязвате.

След това разширявам JLabel:

Това е така, защото искам да поставя изображението си в лентата за превъртане, т.е. покажете част от изображението и превъртете потребителя според нуждите.

Така че използвам JScrollPane, за да държа MapLabel, който съдържа само MapIcon.

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

Ето как го правя (малко повече информация за това как да качите изображение):

Ако използвате JPanels, вероятно работите със Swing. Опитай:

Изображението вече е ротационен компонент. Той става обект на условията за връзка като всеки друг компонент.

Следвах този урок за Android и мисля, че върши страхотна работа при зареждане на изображения, без да блокира основния потребителски интерфейс. Освен това се справя с кеширането и превъртането през много изображения: зареждайте ефективно големи растерни изображения