6
October

Игра “Меморина” (Java Swing GUI Game) и проблема с ImageIcon

Posted in: Java GUI, Swing, AWT, SWT, Java technologies, J2SE |

Ну прямо гейм-девелопер какой-то.
Попросили меня написать маленькую игрушечку с использованием графической библиотеки Java Swing. Игра всем знакома и называется “Меморина”.
Думаю, заказчик не будет сильно зол за то, что я выложу игру на всеобщее обозрение…
Еще столкнулся с такой проблемой: при загрузке картинок из jar-файла возникает исключительная ситуация ImageFormatException, хотя при запуске из IDE все проходит без ошибок.

Для тех, кому хочется поскорее увидеть игрушку, - memory.zip (54 Kb)
А вот stack-trace того, что я увидел после запаковки классов и иконок в jar:

Premature end of JPEG file
sun.awt.image.ImageFormatException: JPEG datastream contains no image
  at sun.awt.image.JPEGImageDecoder.readImage(Native Method)
  at sun.awt.image.JPEGImageDecoder.produceImage(Unknown Source)
  at sun.awt.image.InputStreamImageSource.doFetch(Unknown Source)
  at sun.awt.image.ImageFetcher.fetchloop(Unknown Source)
  at sun.awt.image.ImageFetcher.run(Unknown Source)

В результате небольшого разбирательства обратил внимание на этот код:

  InputStream is = Memorina.class
        .getResourceAsStream(iconName);
  byte[] buffer = new byte[is.available()];
  is.read(buffer);
  ImageIcon imgIcon = new ImageIcon(buffer);

Экземпляр класса ImageIcon использовался для создания объекта JButton.
Но ImageIcon можно получить и другим способом:

  ImageIcon imgIcon = new ImageIcon(img),

где img - объект Image.
Этот объект можно получить через java.awt.Toolkit. В итоге получаем следующий код, который отлично достает картинки из jar’a:

  URL url = Memorina.class.getResource(iconName);
  Image img = Toolkit.getDefaultToolkit().getImage(url);

Проблема решена.
Жду ваших комментариев и замечаний.

5 Comments »

RSS feed for comments on this post.



June 7, 2006 #

Думаю проблема в строчке

byte[] buffer = new byte[is.available()];

Вероятно InputStream, возвращаемый класслодером для ресурса из jar-ки не реализует метод available (честно говоря и не должен), и возвращает всегда 0. Т.е. закладываться на этот метод в данном случае нельзя. Нужно сделать ByteArrayOutputStream baos, скопировать в него при помощи буфера фиксированого размера то что нужно из InputStream, и потом использовать byte[] полученый из baos.toByteArray().

June 7, 2006 #

Предположение хорошее, но я это тоже проверял. Дело в том, что при запуске программы из IDE все работает, а не работает именно после запаковки классов и картинок в jar.

June 7, 2006 #

ХМ. странно. такого быть не должно. А в пути к самой jar-ке случаем нет папки, имеющей в имени восклицательный знак.

June 7, 2006 #

Нету, но восклицательный знак - не проблема. Попробуй написать простенькую програмку используя куски кода из статьи и убедишься сам. Я использовал JDK 1.4.2, может в 1.5 уже все и исправили…

m1
March 24, 2007 #

А можно полный исходник ? Или тогда заказчик уж точно обидется?

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>