2013-09-09 2 views
0

Я написал Java7-приложение, которое создает BufferedImage, который нарисован фоновым потоком всякий раз, когда пользователь меняет что-то, что влияет на изображение. Проблема заключается в том, что при отображении изображения правильное изображение отображается только на несколько секунд, затем отображается неустойчивый багаж (в нужном размере) с остатками буфера кадра из системы (см. Изображение на imgur, справа).Отображение Java BufferedImage на MacBook с отображением Retina не работает

http://i.imgur.com/l3O8IjD.jpg

(Вот что он должен выглядеть следующим образом: http://i.imgur.com/AFWZIzz.png)

Как только рисунок нить закончится, BufferedImage будет обращено на компонент JPanel после трансформируются с AffineTransformation, чтобы отразить определенный уровень масштабирования.

Размер BufferedImage определяется фиксированным числом, которое не зависит от разрешения MacBook или JFrame (обычно довольно высокое, что-то вроде 4000x2000). Панель, в которой вызывается BufferedImage, находится внутри ScrollPanel, которая настраивается на размер панели. Не имеет значения, записывается ли BufferedImage поверх или создается новый каждый раз, когда новая версия рисуется потоком.

Я тестировал инструмент на окнах, MacBook без дисплея сетчатки и три MacBook с дисплеем сетчатки, на всех машинах без дисплея сетчатки, инструмент отлично работает. Есть идеи?

Редактировать: так работает программа: Класс HexaVisExplorer.java - это графический интерфейс JFrame, созданный с помощью NetBeans проекта. Он содержит ScrollPane и VisualizationPanel.java, который является содержимым ScrollPane, и всякий раз, когда пользователь изменяет свойство, влияющее на результирующее изображение, ActionListener для компонента вызывает метод в VisualizationPanel. Там свойство задано и поток инициализируется и запускается, что на основе свойств, установленных в VisualizationPanel.java, нарисует новый BufferedImage. Когда это будет сделано, новый BufferedImage будет сохранен в VisualizationPanel.java, который затем будет перекрашен с переопределенной paintComponent(), где изображение будет преобразовано с использованием java.awt.geom.AffineTransform ation для эффективное масштабирование. Наконец, видовой экран scrollpane изменяется, чтобы отобразить новый размер изображения. Вот код:

Класс HexavisExplorer.java

public class HexaVisExplorer extends javax.swing.JFrame { 

    private VisualizationPanel visualizationPanel; 
    private javax.swing.JScrollPane jScrollPane1; 

    public HexaVisExplorer() { 
     //...Example where a component listener calls a method in VisualizationPanel.java to set a property 
     polygonBorderCheckbox.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       visualizationPanel.setPolygonBorders(polygonBorderCheckbox.isSelected()); 
      } 
     }); 
     //... 
    } 
} 

Класс VisualizationPanel.java. recalculate() создает новый VisualizationThread.java, который генерирует BufferedImage в вопросе, используя свойства в VisualizationPanel.java. Когда Пересчитать является finisehd,

public class VisualizationPanel extends JPanel { 

    private boolean polygonBorders; 
    //here be more property class variables and getter/setter for them 

    public void setPolygonBorders(boolean polygonBorders) { 
     this.polygonBorders = polygonBorders; 
     recalculate(); 
     this.revalidate(); 
     this.repaint(); 
    } 

    public void recalculate(){ 
     vt = new VisualizationThread(this); 
     vt.execute(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 


     Graphics2D g2d = (Graphics2D) g; 
     g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); 
     dataTransformation.setToScale(transform_factor, transform_factor); 
     g2d.transform(dataTransformation); 
     g2d.drawImage(toDraw, 0, 0, null); 
     this.setSize((int) Math.ceil(transform_factor * maxwidth), (int) Math.ceil(transform_factor * maxheight)); 
     this.setPreferredSize(new Dimension((int) Math.ceil(transform_factor * maxwidth), (int) Math.ceil(transform_factor * maxheight))); 
     this.revalidate(); 
     hx.modifyVisPanelViewport(this); 
    } 
} 

VisualizationThread.java принимает VisualizationPanel, читает его свойства и вычисление нового BufferedImage на его основе. Когда это сделано, вызывается done(), который затем устанавливает новый BufferedImage для рисования на VisualizationPanel и его рецензирование.

public class VisualizationThread extends SwingWorker<Object, Object> { 
    private VisualizationPanel vp; 
    private BufferedImage toDraw; 

    @Override 
    protected Object doInBackground() throws Exception { 
    // The bufferedImage gets drawn on here. 
    } 

    @Override 
    protected void done() { 
     vp.setToDraw(toDraw); 
     vp.setPreferredSize(new Dimension(toDraw.getWidth(), toDraw.getHeight())); 
     vp.repaint(); 
     vp.revalidate(); 
    } 
} 

Вот что он должен выглядеть следующим образом:

+1

Показать код, без этого мы не действительно имеют необходимую нам информацию, чтобы помочь – StormeHawke

+0

вы используете 'AffineTransformOp'? – trashgod

+0

dataTransformation - java.awt.geom.AffineTransform, поэтому я не использую AffineTransformOp. Я добавил код, надеюсь, теперь вы сможете понять лучше! – jurib

ответ

1

Это выглядит как компонент пэра хозяина ожидает, чтобы сделать изображение с одной цветовой модели, но сталкиваясь с другой. Есть слишком много способов для этого, чтобы пойти не так, для окончательного ответа, но everal вещи носит более пристальное внимание:

  • Убедитесь, что BufferedImage имеет совместимую модель цвета и пространство, для example.

  • Рассмотрите масштабирование с помощью AffineTransformOp, набросанное here, так как оно может создать «целевое изображение с правильным размером и количеством полос».

  • Пока done() выполнен на event dispatch thread, проверьте, чтобы остальная часть вашей программы была правильно синхронизирована.