gpt4 book ai didi

java - 将组件绘制到 BufferedImage 会导致显示损坏

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:10:33 26 4
gpt4 key购买 nike

我正在使用 JScrollNavigator组件描述 here ,为了提供一个导航窗口到一个大型的“类似 Canvas ”的 CAD 组件,我已经嵌入了 JScrollPane .

我试图适应 JScrollNavigator绘制 Canvas 的缩略图以为用户提供一些额外的上下文。但是,这样做会导致我的应用程序主框架的渲染损坏。具体就是调用paint(Graphics)的 Action 在视口(viewport)组件(即我的主 Canvas )上,传入 GraphicsBufferedImage 创建的对象导致后续显示损坏;如果我注释掉这一行,一切正常。

以下是JScrollNavigator的覆盖 paintComponent方法:

@Override
protected void paintComponent(Graphics g) {
Component view = jScrollPane.getViewport().getView();
BufferedImage img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();

// Paint JScrollPane view to off-screen image and then scale.
// It is this action that causes the display corruption!
view.paint(g2d);
g2d.drawImage(img, 0, 0, null);
Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);

super.paintComponent(g);
g.drawImage(scaled, 0, 0, null);
}

有没有人对腐败的原因有任何建议?我会认为绘制到屏幕外图像应该对现有的绘制操作没有影响。

编辑

提供一些额外的细节: JScrollNavigatorJSplitPane 的左侧形成一个子面板. JScrollPane与导航器相关联的位于右侧。 “损坏”导致不再呈现拆分器并且滚动条不可见(它们显示为白色)。如果我调整 JFrame 的大小, JMenu段也变白了。如果我尝试使用导航器或与滚动条交互,它们会变得可见,但分隔符仍为白色。就好像各种组件的不透明设置已受到视口(viewport) View 渲染到屏幕外图像的影响。

另外,如果我制作 JScrollNavigator出现在一个完全独立的 JDialog ,一切正常。

编辑 2

我可以重现问题 始终如一 通过执行以下操作:

添加 JMenuBarmFrame :
JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);

main() JScrollNavigator的方法代替:
jsp.setViewportView(textArea);

... 和:
jsp.setViewportView(new JPanel() {
{
setBackground(Color.GREEN);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
}
});

确保 JScrollNavigator作为面板嵌入 mFrame ,而不是作为单独的 JDialog 出现:
mFrame.add(jsp, BorderLayout.CENTER);
mFrame.add(nav, BorderLayout.NORTH);

现在,当应用程序运行时 JMenuBar 不再可见 ;将 View (即带有粗黑色边框的绿色 JPanel)绘制到 Graphics2D 的行为返回者 BufferedImage.createGraphics()实际上似乎正在渲染它 屏幕 ,可能来自 JFrame 的左上角,从而遮挡了其他组件。这似乎只有在 JPanel 时才会发生用作视口(viewport) View ,而不是其他组件,例如 JTextArea , JTable , 等等。

编辑 3

看起来这个人有同样的问题(虽然没有发布解决方案): http://www.javaworld.com/community/node/2894/

编辑 4

这是 mainpaintComponent导致编辑 2 中描述的可重现错误的方法:
public static void main(String[] args) {
JScrollPane jsp = new JScrollPane();
jsp.setViewportView(new JPanel() {
{
setBackground(Color.GREEN);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
}
});

JScrollNavigator nav = new JScrollNavigator();
nav.setJScrollPane(jsp);

JFrame mFrame = new JFrame();

JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);

mFrame.setTitle("JScrollNavigator Test");

mFrame.setSize(800, 600);

mFrame.setLayout(new GridLayout(1, 2));

mFrame.add(jsp);
mFrame.add(nav);
Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
mFrame.setLocation((screenDim.width - mFrame.getSize().width) / 2, (screenDim.height - mFrame.getSize().height) / 2);

mFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mFrame.setVisible(true);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

Component view = jScrollPane.getViewport().getView();

if (img == null) {
GraphicsConfiguration gfConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
}

Graphics2D g2d = img.createGraphics();
view.paint(g2d);

Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);

g.drawImage(scaled, 0, 0, null);
}

编辑 5

其他人似乎无法重现确切的问题。我会要求人们运行粘贴的代码 here .当我第一次运行这个例子时,我看到以下内容:

Corrupt Image 1

JScrollNavigator 或 JMenuBar 都没有被绘制;这些框架区域是透明的。

调整大小后,我看到以下内容:

Corrupt Image 2
JMenuBar还没有绘制(paint),看来 JPanel在某个时间点呈现在 (0,0) (应该是 JMenuBar 的位置)。 view.paint电话内 paintComponent是造成这种情况的直接原因。

最佳答案

摘要:原文 JScrollNavigator 使用 Swing opacity 属性呈现方便的绿色 NavBox在相邻 JScrollPane 中组件的缩放缩略图上.因为它扩展了 JPanel ,(共享)UI 委托(delegate)对 opacity 的使用与可滚动组件的冲突。在上面编辑 5 中看到的图像代表了相关的渲染工件,也显示了 here .解决办法是让NavBox , JScrollNavigator和可滚动组件扩展 JComponent ,正如下面第二个附录中所建议的那样。每个组件然后可以单独管理它自己的属性。

enter image description here

我在您的 code as posted 中没有看到异常的渲染伪像在我的平台上,Mac OS X,Java 1.6。抱歉,我没有看到任何明显的便携性违规。

image one

一些可能不相关但可能有用的观察。

  • 即使您使用 setSize() ,在这种情况下,您仍然应该pack()内附Window .
    f.pack();
    f.setSize(300, 200);
  • 为方便起见,add()将组件转发到内容 Pane 。
    f.add(nav, BorderLayout.WEST);
  • 首选 StringBuilderStringBuffer .
  • 考虑 ComponentAdapter代替 ComponentListener .

  • 附录:如建议 here , 我使用 RenderingHints 得到了更灵活的结果而不是 getScaledInstance()如下所示。添加一些图标可以更轻松地查看图像和文本上的不同效果。

    image two
    editPane.insertIcon(UIManager.getIcon("OptionPane.errorIcon"));
    editPane.insertIcon(UIManager.getIcon("OptionPane.warningIcon"));
    ...
    @Override
    protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Component view = jScrollPane.getViewport().getView();
    BufferedImage img = new BufferedImage(view.getWidth(),
    view.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D off = img.createGraphics();
    off.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_ON);
    off.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
    RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    view.paint(off);
    Graphics2D on = (Graphics2D)g;
    on.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    RenderingHints.VALUE_ANTIALIAS_ON);
    on.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
    RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    on.drawImage(img, 0, 0, getWidth(), getHeight(), null);
    }

    附录二:看起来像 JPanel UI 委托(delegate)不合作。一种解决方法是扩展 JComponent以便您可以控制 opacity .管理 backgroundColor 只需稍微多一点的工作. NavBoxJScrollNavigator也是类似治疗的候选人。

    enter image description here
    jsp.setViewportView(new JComponent() {

    {
    setBackground(Color.red);
    setBorder(BorderFactory.createLineBorder(Color.BLACK, 16));
    }

    @Override
    protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(getBackground());
    g.fillRect(0, 0, getWidth(), getHeight());
    }

    @Override
    public Dimension getPreferredSize() {
    return new Dimension(300, 300);
    }
    });

    关于java - 将组件绘制到 BufferedImage 会导致显示损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11739989/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com