【问题标题】:Some part of the image disappears when I scroll up and down on a jscrollpane当我在 jscrollpane 上上下滚动时,图像的某些部分消失了
【发布时间】:2019-12-09 16:54:38
【问题描述】:

大家好,我在JPanel 中绘制的图像有问题。将图像绘制到面板时没有问题。当我向上或向下滚动图像时出现问题。当再次返回该部分时,在视口中看不到的图像部分被涂成白色。

我在JPanel 中添加了BufferedImage。我还可以使用AffineTransform 调整图像大小。问题是当我在图像中添加JScollPane 时,每当我向上或向下滚动scrollpane 时,图像的某些部分就会消失..

我也尝试使用drawRenderedImage,它确实解决了滚动问题,但它搞砸了其他功能。

这是我能做的最简洁的代码;

package convert;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;

public class ZoomTest {

    public static void main(String[] args) {
        ImagePanel panel = new ImagePanel();

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().add(new JScrollPane(panel));
        f.setSize(1200, 1200);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ImagePanel extends JPanel {

    BufferedImage image;
    double scale;

    public ImagePanel() {
        loadImage();
        scale = .38;
        addMouseWheelListener(new MouseWheelListener() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                int rotation = e.getWheelRotation();
                if (rotation < 0) {
                    scale -= .05;
                } else {
                    scale += .05;
                }
                if (scale < 0) {
                    scale = 0;
                }

                revalidate();
                repaint();

            }
        });

    }

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

        double x = (getWidth() - scale * image.getWidth()) / 2;
        double y = (getHeight() - scale * image.getHeight()) / 2;

        AffineTransform at = new AffineTransform();
        at.translate(x, y);

        at.scale(scale, scale);
        g2.setTransform(at);

        g2.drawImage(image, 0, 0, null);

    }

    public Dimension getPreferredSize() {
        int w = (int) (scale * image.getWidth());
        int h = (int) (scale * image.getHeight());
        return new Dimension(w, h);
    }

    private void loadImage() {
        String fileName = "c:\\users\\john ebarita\\downloads\\lorem-ipsum-1.jpg";
        try {
            image = ImageIO.read(new File(fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【问题讨论】:

  • 首先使用Graphics2D g2 = (Graphics2D) g.create(); 而不是Graphics2D g2 = (Graphics2D) g;paintComponent 方法的末尾添加g2.dispose()
  • 很抱歉,我已经这样做了,但还是没有运气。
  • 这可能是JScrollPane 工作方式的问题。我会考虑通过在paintComponent 方法之外缩放图像(进入“缩放”变量)来说明,然后简单地绘制缩放版本
  • 你能重现这个场景吗?
  • 是的,JScrollPane 进行了高度优化,它需要组件的小“快照”,然后根据需要简单地附加,因此在 paintComponent 方法中进行缩放可能会与这个 blitting 过程搞砸

标签: java swing jscrollpane mousemotionlistener


【解决方案1】:

看看Graphics2D#drawImage(Image, AffineTransform, ImageObserver)。可能会有帮助。

package convert;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;

public class ZoomTest2 {
  public static void main(String[] args) {
    ImagePanel panel = new ImagePanel();
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(new JScrollPane(panel));
    f.setSize(1200, 1200);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class ImagePanel extends JPanel {
  BufferedImage image;
  double scale;

  public ImagePanel() {
    loadImage();
    scale = .38;
    addMouseWheelListener(new MouseWheelListener() {
      @Override
      public void mouseWheelMoved(MouseWheelEvent e) {
        int rotation = e.getWheelRotation();
        if (rotation < 0) {
          scale -= .05;
        } else {
          scale += .05;
        }
        if (scale < 0) {
          scale = 0;
        }
        revalidate();
        repaint();
      }
    });
  }

  @Override
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g.create();

    double x = (getWidth() - scale * image.getWidth()) / 2;
    double y = (getHeight() - scale * image.getHeight()) / 2;
    AffineTransform at = new AffineTransform();
    at.translate(x, y);
    at.scale(scale, scale);

    // g2.setTransform(at);
    // g2.drawImage(image, 0, 0, this);
    g2.drawImage(image, at, this);

    // or:
    // AffineTransform atf = g2.getTransform();
    // atf.concatenate(at);
    // g2.setTransform(atf);
    // g2.drawImage(image, 0, 0, this);

    g2.dispose();
  }

  public Dimension getPreferredSize() {
    int w = (int)(scale * image.getWidth());
    int h = (int)(scale * image.getHeight());
    return new Dimension(w, h);
  }

  private void loadImage() {
    String fileName = "aaa.png";
    try {
      image = ImageIO.read(new File(fileName));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

【讨论】:

  • 谢谢。连接工作。对不起,打扰你。我对摇摆真的很陌生。我以前用过弹簧。
  • 旋转这张图片怎么样
【解决方案2】:

这里是您的问题的解决方案。自定义绘画我也运气不好,所以我的解决方案是直接更新鼠标滚轮上的图像并将其设置为标签。

import java.awt.Image;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;

public class ZoomTest {

    public static void main(String[] args) {
        ImagePanel panel = new ImagePanel();

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().add(new JScrollPane(panel));
        f.setSize(1000, 1000);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ImagePanel extends JLabel {

    BufferedImage image;

    double scale;

    public ImagePanel() {
        setHorizontalAlignment(SwingConstants.CENTER);
        loadImage();
        scale = .38;
        updateImage();
        addMouseWheelListener(new MouseWheelListener() {

            @Override
            public void mouseWheelMoved(MouseWheelEvent e) {
                int rotation = e.getWheelRotation();
                if (rotation < 0) {
                    scale -= .05;
                } else {
                    scale += .05;
                }
                if (scale < 0) {
                    scale = 0;
                }
                updateImage();
                revalidate();
                repaint();

            }
        });

    }

    private void updateImage() {
        int w = (int) (scale * image.getWidth());
        int h = (int) (scale * image.getHeight());
        setIcon(new ImageIcon(image.getScaledInstance(w, h, Image.SCALE_SMOOTH)));
    }

    private void loadImage() {
        String fileName = "c:\\users\\john ebarita\\downloads\\lorem-ipsum-1.jpg";
        try {
            image = ImageIO.read(new File(fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【讨论】:

  • 我觉得我不能使用JLabel,因为它会降低应用程序的性能
  • @John 为什么你认为JLabel 会降低性能?每幅画的图像转换都需要更高的性能。
  • “自定义绘画”是给懒人的
  • JLabels 适合懒人
猜你喜欢
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 2020-06-27
  • 2021-04-16
相关资源
最近更新 更多