Dynamically resize jframe/image or scroll

2019-01-28 12:47发布

问题:

As discussed in this question (Wrap image to Jframe), i need a jframe to match the exact provided image (The image itself is originally a PDF which has been converted to an image)

The solution provided does indeed build a jframe to my image dimensions, but i can't actually see all of the image. I need to be able to resize the jframe, with the image dynamically adjusting to the new jframe size. Failing that, i think if i could just scroll the jframe or even zoom in or out, i could at least get to the parts of the image that i currently cannot see.

The reason i need this is that, within my code, i have an option to draw a Rectangle2D against the image - the code spits out the co-ordinates as java.awt.geom.Rectangle2D$Float[x,y,w,h].

I will then use these co-ordinates to extract the region against the original PDF using PDFTextStripperbyArea class from Apache PDFbox. PDFTextStripperbyArea takes its input as Rectangle2D measurements. Hence, the image and the jframe must always be the same size in order to retrieve accurate co-ordinates.

Can anybody help?

回答1:

To warp the label with a scroll pane you could implement the following changes:

    //frame.setLayout(new FlowLayout()); - comment out -  use default (Borderlayout)
    JLabel lbl= new JLabel();
    lbl.setIcon(icon);
    JScrollPane jsp = new JScrollPane(lbl); //warp the label with a scrollpane 
    //frame.add(lbl); 
    frame.add(jsp); //add scrollpane to frame instead of lbl

You can find more information here.



回答2:

Carrying on from your previous question, your basic question comes down to two issues.

  1. How to determine when the component has changed size
  2. Scaling the image to meet the new requirements.

To be frank, there are any number of examples available on both subjects, you just need to combine them. You could start by having a look at:

  • maintaining aspect ratio of JPanel background image
  • Quality of Image after resize very low
  • Resizing icon to fit on JButton in Java?

The following is a modification of the ImagePanel I presented in your previous question which will scale the image based on the size of the component while maintaining the aspect ratio.

public class ImagePane extends JPanel {

    private BufferedImage img;
    private Image scaled;

    public ImagePane(BufferedImage img) {
        this.img = img;
        this.scaled = img;
        addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                Dimension size = getSize();
                if (size.width > size.height) {
                    size.width = -1;
                } else {
                    size.height = -1;
                }
                scaled = img.getScaledInstance(size.width, size.height, java.awt.Image.SCALE_SMOOTH);
            }

        });
    }

    @Override
    public Dimension getPreferredSize() {
        return scaled == null ? new Dimension(0, 0) : new Dimension(scaled.getWidth(this), scaled.getHeight(this));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (scaled != null) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.drawImage(scaled, 0, 0, this);
            g2.dispose();
        }
    }
}

The example is provide for brevity, Image#getScaledInstance is neither the fastest nor does it generate the best quality result. The first two examples linked above go into more detail about other possible solutions.

You will also want to calculate and maintain the resulting scaling factor, which would need to be applied to any additional painting operations.

In this case, I might be tempted to simply calculate the scaling factor (instead of scaling the image) and use a AffineTransform in the paintComponent to apply it, but that all comes down to needs