日期:2014-05-20  浏览次数:20891 次

java多层组件内画图
将图片按照一定比率缩放成固定的大小,然后画在JComponent上。如果直接将JComponent添加到JFrame上,图片完美显示。如果先添加到JPanel再添加到JFrame内,将JFrame拖大之后,图片显示就有问题了。麻烦各位大侠帮忙看看是什么地方出了问题。代码如下

Java code
import javax.imageio.*;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.io.*;

public class ImgP extends JFrame{
    ImageCanvas ic;

    final double culculateRatio(int width, int height){//计算缩放比例
        double ratio;
        if(getWidth()>=width && getHeight()>=height){
            ratio = 1;
            return ratio;
        }
        if((double)getWidth()/width > (double)getHeight()/height)
            ratio = (double)getHeight() / height;
        else ratio = (double)getWidth() / width;
        return ratio;
    }

    public ImgP(){
        Image image;
        double ratio;
        setSize(700, 500);
        try {
            image = ImageIO.read(new File("G:\\Image\\IMG_0783.jpg"));
            ratio = culculateRatio(image.getWidth(null),image.getHeight(null));
            ic = new ImageCanvas(ratio);
            ic.setImage(image);
           //如果将add(ic)一行替换成以下代码,画图有误
           //JPanel panel = new JPanel();
            //panel.add(ic);
           //add(panel);
            add(ic);
            ic.concateZoom(ratio);
        } catch (IOException ex) {
        }
    }
    
    public static void main(String[] args) {
        ImgP ip = new ImgP();
        ip.setVisible(true);
        ip.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

    class ImageCanvas extends JComponent{
        Image img;
        double ratio;
        AffineTransform af = AffineTransform.getScaleInstance(1,1);
        public ImageCanvas(double ratio){
            this.ratio = ratio;
        }
        void setImage(Image m){
            img = m;
            paintImmediately(getBounds());
            //concateZoom(0.3);
        }
        void concateZoom(double scale){
            if (img==null)return;
            af.preConcatenate(AffineTransform.getScaleInstance(scale,scale));
            paintImmediately(getBounds());
        }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img==null) {
                g.setColor(Color.BLACK);
                g.fillRect(0,0,getWidth(),getHeight());
            }
            else {
                Graphics2D g2d = (Graphics2D)g;
                g2d.setTransform(af);
                g2d.drawImage(img, (int)(((getWidth()-img.getWidth(null)*ratio)/2)/ratio),
                        (int)(((getHeight()-img.getHeight(null)*ratio)/2)/ratio), this);
            }
        }
    @Override
    public Dimension getPreferredSize() {return new Dimension(600, 400);}
    }



------解决方案--------------------
把JPanel panel = new JPanel();
修改成为
JPanel panel = new JPanel(new BorderLayout());试试看
------解决方案--------------------
FlowLayout是流布局,每个组件上下左右都有间隔,间隔太远就看不到了。

borderLayout是边框布局,每次放一个组件而又没有规定组件位置的话,默认放置到中间位置