java - 在配备 Retina 显示屏的 MacBook 上显示 Java BufferedImage 不起作用

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

我编写了一个Java7应用程序,它创建一个BufferedImage,每当用户更改对图像有影响的内容时,后台线程就会使用它。问题是,当显示图像时,正确的图像仅显示几秒钟,然后显示不稳定的图像(大小正确)以及来自系统的帧缓冲区的其余部分;见下图:

image

它应该是这样的:

correct image

一旦绘制线程完成,BufferedImage 将在使用 AffineTransformation 进行转换后绘制到 JPanel 组件上以反射(reflect)一定的缩放级别。

BufferedImage 的大小由固定数字决定,该数字不依赖于 MacBook 或 JFrame 的分辨率(通常相当高,例如 4000x2000) 。绘制 BufferedImage 的面板位于可根据面板大小进行调整的 ScrollPane 内。每次线程绘制新版本时,BufferedImage 是否被重写或创建新的并不重要。

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

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

类 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,方法recalculate()创建一个新的VisualizationThread,它使用以下方法生成有问题的BufferedImage VisualizationPanel 中的属性。当重新计算完成后,

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 采用一个 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();
    }
}

最佳答案

看起来就像主机对等组件期望使用一种颜色模型渲染图像,但遇到另一种颜色模型。有太多的方法会导致这个问题无法得到明确的答案,但有几件事需要仔细审查:

  • 验证您的 BufferedImage 是否具有兼容的颜色模型和空间,例如 example .

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

  • done()event dispatch thread 上执行时,验证程序的其余部分是否正确同步,对于 example .

关于java - 在配备 Retina 显示屏的 MacBook 上显示 Java BufferedImage 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18700080/

相关文章:

java - 在外部提供一个 for 循环的变量。这怎么可能?

java - 关闭映射流 - 什么意思?

java - 将对模型元素(jlist)所做的更改更新到 mysql 数据库,问题

java - JColorChooser和JFileChooser开放问题

java - Mac 上的 Neo4j : Prevent org. neo4j.server.Bootstrapper 出现在 dock 中

macos - 安装 Yeoman 后如何修复 "yo: command not found"

java - 查找 2 个 git 提交之间可用的分支

java - Play Framework : How to compile an application with the option "-Xlint:unchecked"?

java - 禁用禁用按钮的工具提示

python - 在 Mountain Lion 中执行 ex mkvirtualenv 时出错