2014-11-17 10 views
0

У меня есть простое приложение Swing/AWT, которое работает в полноэкранном режиме в Windows. У меня есть несколько разных PNG-файлов, которые он загружает как свое собственное фоновое изображение в зависимости от контекста.Как загрузить изображения в фоновом режиме в приложении Swing?

Он загружает их так:

BufferedImage bufferedImage; 
bufferedImage = ImageIO.read(getClass().getResource("/bg1.png")); 
Image bgImage1 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH); 
bufferedImage = ImageIO.read(getClass().getResource("/bg2.png")); 
Image bgImage2 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH); 
bufferedImage = ImageIO.read(getClass().getResource("/bg3.png")); 
Image bgImage3 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH); 

А потом рисует их так:

window.repaint(); 
graphics.drawImage(bgImage1, 0, 0, null); 
// draw some other stuff too, like text 

И только тщательное, window является JWindow переменной и graphics является Graphics2D переменной.

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

window.repaint(); 
graphics.drawImage(bgImage2, 0, 0, null); 
// draw some other stuff too, like text 

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

Как я могу заставить его загружать эти изображения беззвучно? Как в ... как мне избежать рисования белого белого экрана в течение секунды, в первый раз он отображает новое фоновое изображение? Все последующие времена уже мгновенные, вероятно, потому, что они действительно захватили их в память в этот момент. Но просто называть getScaledInstance, по-видимому, недостаточно, чтобы поместить вещи в память, потому что она на самом деле не мерцает, пока я не позвоню drawImage по линии.

+0

Вам следует подумать о предоставлении запускаемого примера, демонстрирующего вашу проблему. Одна из проблем, которые могут возникнуть у вас, заключается в том, что вы не передаете ImageObserver методу drawImage ... – MadProgrammer

ответ

2

ImageIcon будет загружен в фоновом режиме как функция.

Вы также можете сделать это довольно легко с фоновым потоком т.д .:

final String path = "/example.png"; 
new SwingWorker<BufferedImage, Void>() { 
    @Override 
    public BufferedImage doInBackground() throws IOException { 
     return ImageIO.read(ClassName.class.getResource(path)); 
    } 
    @Override 
    public void done() { 
     try { 
      BufferedImage img = get(); 
      // put img somewhere 
     } catch(InterruptedException ignored) { 
     } catch(ExecutionException ex) { 
      ex.printStackTrace(System.err); 
     } 
    } 
}.execute(); 

Кроме того,

window.repaint(); 
graphics.drawImage(bgImage2, 0, 0, null); 

Это беспокоит меня немного. В общем случае нам не нужно запрашивать repaint всего контейнера верхнего уровня. Вы также не должны использовать getGraphics() для рисования.

Компоненты Swing верхнего уровня являются двойными буферами, но если вы рисуете за пределами структуры краски, вы не получите этого. Это приведет к мерцанию.

Два хороших источников для правильной пользовательской картины являются:

живописи должно быть сделано пассивно перекрывая paintComponent на JComponent.JLabel также может отображать ImageIcon как функцию, поэтому вам необязательно делать обычную покраску, если вы просто хотите отобразить изображение.

+0

Вот мой код для «графика»: «final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice screen = ge.getDefaultScreenDevice(); JWindow window = new JWindow(); window.setVisible (true); Graphics2D graphics = (Graphics2D) window.getGraphics(); ' – SoaperGEM

+1

Да, это приведет к мерцанию, а также к другим аномальным проблемам. Пользовательскую покраску нужно выполнить в 'paintComponent'. – Radiodef

0

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

+0

Почему же я не замечаю мерцание, пока не назову 'drawImage'? Когда мое приложение инициализируется, я сразу же масштабирую все три изображения, а затем отображу один из них. Но только через несколько минут, когда я назову 'drawImage' на одном из двух других, я сначала вижу этот белый экран. – SoaperGEM

Смежные вопросы