使用Retina显示在MacBook上显示Java BufferedImage不起作用

时间:2013-09-09 14:03:58

标签: java swing osx-mountain-lion retina-display

我编写了一个Java7-Application,它创建了一个BufferedImage,只要用户更改了对图像有影响的内容,就会被后台线程绘制。问题在于,当显示图像时,正确的图像仅显示几秒钟,然后显示来自系统的帧缓冲区的静止不稳定(大小合适)(参见右图中的图像) )。

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

(以下是它应该是什么样的:http://i.imgur.com/AFWZIzz.png

绘图线程完成后,BufferedImage将在用AffineTransformation转换后绘制到JPanel组件上,以反映某个缩放级别。

BufferedImage的大小由固定数字决定,该数字不依赖于MacBook或JFrame的分辨率(通常非常高,类似于4000x2000)。绘制BufferedImage的面板位于ScrollPanel内,可调整为Panel的大小。每次线程绘制新版本时,BufferedImage是写入还是创建新的无关紧要。

我已经在Windows上测试了这个工具,没有视网膜显示器的MacBook和三个带视网膜显示屏的MacBook,在没有视网膜显示的所有机器上,该工具完美运行。有什么想法吗?

编辑:这是程序的工作方式:类 HexaVisExplorer.java 是使用项目的NetBeans构建的JFrame GUI。它保留了ScrollPane和作为ScrollPane内容的 VisualizationPanel.java ,每当用户更改对结果图像有影响的属性时,组件的ActionListener都会调用方法中的方法。 VisualizationPanel。在那里,设置了一个属性,并初始化并启动了一个Thread,根据 VisualizationPanel.java 中设置的属性,将绘制一个新的BufferedImage。完成此操作后,新的BufferedImage将保存到 VisualizationPanel.java ,然后将使用重写的paintComponent()重新绘制,其中将使用 java.awt转换图像。 .geom.AffineTransform 用于高效缩放。最后,滚动窗格的视口会被修改以反映新的图像大小。这是代码:

Class 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 ,它使用 VisualizationPanel.java 中的属性生成相关的BufferedImage。当重新计算是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 个答案:

答案 0 :(得分:1)

看起来就像主机对等组件期望使用一种颜色模型渲染图像但遇到另一种颜色模型一样。对于一个明确的答案,出现这种情况的方法太多了,但是几件事情需要仔细审查:

  • 验证BufferedImage AffineTransformOp是否具有兼容的颜色模型和空格,适用于example

  • 考虑使用done()进行缩放,概述here,因为它可以创建“具有正确大小和数量的波段的目标图像”。

  • event dispatch thread上执行{{1}}时,请验证您的程序的其余部分是否已正确同步。