简单的Java swing应用——图片查看器()

 

该篇主要运用Java swing的基础知识,展示的应用结果。

用到的内容:

import swingTool.ImageView;

import javax.imageio.ImageIO;(本文主要是读文件)
import javax.swing.*;
import javax.swing.border.Border;(对于边框的复合使用)
import java.awt.*;
import java.awt.event.MouseAdapter;(鼠标适配器,实现了各类鼠标事件,写起来更简洁)
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

具体应用到的知识,大家可以向我询问,我尽力解决。本人还在努力学习中,不足之处,多多谅解。

import swingTool.ImageView;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author stardream  Email:stardream0000@163.com
 * @Description
 * @2020/8/25 22:59
 */
public class Test20 extends JFrame {
    JPanel jp1=new JPanel();//上面一排容器
    JPanel jp2=new JPanel();//中间大图容器
    ImageView panel=new ImageView();//画图本质上还是在panel上
    List<ImageButton> imagelist=new ArrayList();
    public Test20(String title) {
        super(title);
        setLayout(new BorderLayout());
        setSize(600, 500);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //将jp1宽度设置足够大,高度不变
        jp1.setPreferredSize(new Dimension(Toolkit.getDefaultToolkit().getScreenSize().width+10,100));//往JScrollPane添加面板时,要设置jp1的尺寸,
                                                                                                              // jsc是根据jp1的尺寸来具体确定是否显示滚动条
        JScrollPane jsp=new JScrollPane(jp1,JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        jsp.setPreferredSize(new Dimension(0,100));
        add(jsp,BorderLayout.NORTH);
        jp2.setLayout(new BorderLayout());
        add(jp2,BorderLayout.CENTER);
        //中间大图
        panel.setScaleType(ImageView.FIT_CENTER);
        panel.setBgColor(Color.WHITE);
        panel.setBorder(BorderFactory.createMatteBorder(1,0,0,0, Color.black));
        jp2.add(panel,BorderLayout.CENTER);
        //上面一排
        jp1.setLayout(new MyXLayoutMan());
        jp1.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        File imagefiles=new File("E:\\java\\images");
        File[]images=imagefiles.listFiles();
        for(File f:images){
            ImageButton imageButton = new ImageButton(f);
            Border lines=BorderFactory.createLineBorder(Color.white);
            Border padding=BorderFactory.createEmptyBorder(5,5,5,5);
            imageButton.setBorder(BorderFactory.createCompoundBorder(padding,lines));
            imageButton.setPreferredSize(new Dimension(100,100));
            imageButton.setBgColor(Color.WHITE);
            imageButton.addMouseListener(new clickListener());
            jp1.add(imageButton,"auto");
            imagelist.add(imageButton);
        }
        setVisible(true);
    }
    class clickListener extends MouseAdapter {
        @Override
        public void mouseClicked(MouseEvent e) {
            ImageButton imagebutton =(ImageButton) e.getSource();
            Image selectedimage = imagebutton.getImage();
            for (ImageButton ib:imagelist) {
                Image image = ib.getImage();
                if(image==selectedimage) {
                    imagebutton.setBorder(BorderFactory.createLineBorder(Color.yellow, 3));
                }else{
                ib.setBorder(BorderFactory.createLineBorder(Color.white,3));}
            }
            panel.showImage(selectedimage);
        }
    }

    public static void main(String[] args) {
        new Test20("图片查看器");
    }
}
class ImageButton extends ImageView{//显示图片按钮
    private File f;
    public ImageButton(File f){
        this.f=f;
        BufferedImage image=null;
        try {
            image = ImageIO.read(f);
        } catch (IOException e) {
            e.printStackTrace();
        }
        showImage(image);
        setScaleType(ImageView.FIT_XY);

    }

}

附上本文所用到的工具类

1、水平布局器

public class MyXLayoutMan implements LayoutManager2
{
    private List<Item> items = new ArrayList<>();
    private int gap = 2;
    private boolean usePerferredSize = false; // 竖立方向是否占满

    public MyXLayoutMan()
    {
    }
    public MyXLayoutMan(int gap)
    {
        this.gap = gap; // 控件之间的间距
    }
    public MyXLayoutMan(int gap, boolean usePerferredSize)
    {
        this.gap = gap;
        this.usePerferredSize = usePerferredSize;
    }

    @Override
    public void addLayoutComponent(String name, Component comp)
    {
        Item item = new Item();
        item.comp = comp;
        item.constraints = "auto";
        items.add(item);
    }

    @Override
    public void removeLayoutComponent(Component comp)
    {
        Iterator<Item> iter = items.iterator();
        while(iter.hasNext())
        {
            Item item = iter.next();
            if(item.comp == comp)
            {
                iter.remove();
            }
        }
    }

    @Override
    public void addLayoutComponent(Component comp, Object constraints)
    {
        Item item = new Item();
        item.comp = comp;
        item.constraints = (String) constraints;
        items.add(item);
    }

    @Override
    public Dimension preferredLayoutSize(Container parent)
    {
        return new Dimension(30,30);
    }

    @Override
    public Dimension minimumLayoutSize(Container parent)
    {
        return new Dimension(30,30);
    }

    @Override
    public Dimension maximumLayoutSize(Container target)
    {
        return new Dimension(30,30);
    }


    @Override
    public void layoutContainer(Container parent)
    {
        // 得到内矩形
        Rectangle rect = new Rectangle(parent.getWidth(), parent.getHeight());
        //Rectangle rect = parent.getBounds();
        Insets insets = parent.getInsets();
        rect.x += insets.left;
        rect.y += insets.top;
        rect.width -= (insets.left + insets.right);
        rect.height -= (insets.top + insets.bottom);

        // 第一轮:过滤到无效的 Item ( 有些控件是隐藏的 )
        List<Item> validItems = new ArrayList<>();
        for(Item it: items )
        {
            if(it.comp.isVisible())
                validItems.add(it);
        }

        // 第二轮处理:百分比,像素,auto的,直接计算出结果; 权重的,在第三轮计算
        int totalGapSize = gap * (validItems.size() - 1);// 间距大小
        int validSize = rect.width - totalGapSize;
        int totalSize = 0;
        int totalWeight = 0;
        for(Item it : validItems)
        {
            Dimension preferred = it.comp.getPreferredSize();
            it.width = preferred.width;
            it.height = usePerferredSize ? preferred.height : rect.height;
            it.weight = 0;

            // 计算宽度
            String cstr = it.constraints;
            if( cstr == null || cstr.length() == 0)
            {
                //System.out.println("(AfRowLayout) Warn: Must define constraints when added to container!");
            }
            else if( cstr.equals("auto"))
            {
            }
            else if(cstr.endsWith("%")) // 按百分比
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
                it.width = validSize * num / 100;
            }
            else if(cstr.endsWith("w")) // 按权重
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-1));
                it.width = 0;
                it.weight = num;
            }
            else if(cstr.endsWith("px")) // 按权重
            {
                int num = Integer.valueOf(cstr.substring(0,cstr.length()-2));
                it.width = num;
            }
            else // 按像素
            {
                int num = Integer.valueOf(cstr);
                it.width = num;
            }

            totalSize += it.width;
            totalWeight += it.weight;

            //System.out.println("计算值:width=" + it.width + ",weight=" + it.weight);
        }

        // 第三轮: 剩余空间按权重分配
        if( totalWeight > 0)
        {
            int remainSize = validSize - totalSize;
            double unit = (double) remainSize / totalWeight;
            for(Item it : validItems)
            {
                if(it.weight > 0)
                {
                    it.width = (int)( unit * it.weight );
                }
            }
        }

        //System.out.println("总宽度: " + rect.width);

        // 第四轮: 按宽度和高度布局
        int x = 0;
        for(Item it : validItems)
        {
            int y = (rect.height - it.height)/2;
            if(x + it.width > rect.width)
                it.width = rect.width - x;
            if(it.width <= 0) break;

            it.comp.setBounds(rect.x + x, rect.y + y, it.width, it.height);

            //System.out.println("宽度: " + it.width);
            x += it.width;
            x += gap; // 间距
        }
    }

    @Override
    public float getLayoutAlignmentX(Container target)
    {
        return 0;
    }

    @Override
    public float getLayoutAlignmentY(Container target)
    {
        return 0;
    }

    @Override
    public void invalidateLayout(Container target)
    {

    }

    ///
    private static class Item
    {
        Component comp;
        String constraints = "auto";
        int width = 0;
        int height = 0;
        int weight = 0;  // 权重
    }


}

2、显示图片工具

public class ImageView extends JPanel
{
    //
    public static final int FIT_XY = 0;
    public static final int FIT_CENTER = 1;
    public static final int FIT_CENTER_INSIDE = 2;

    private Image image;
    private int scaleType = FIT_CENTER;
    private Color bgColor = Color.WHITE; // 背景色

    public ImageView()
    {
        this.setOpaque(false);
    }

    public Image getImage()
    {
        return image;
    }

    public void showImage(Image image)
    {
        this.image = image;
        repaint();
    }

    public int getScaleType()
    {
        return scaleType;
    }

    public void setScaleType(int scaleType)
    {
        this.scaleType = scaleType;
        repaint();
    }

    public Color getBgColor()
    {
        return bgColor;
    }

    public void setBgColor(Color bgColor)
    {
        this.bgColor = bgColor;
        repaint();
    }


    @Override
    protected void paintComponent(Graphics g)
    {
        // 先调用父类的 paintComponent(), 绘制必要的边框和背景
        super.paintComponent(g);

        // 本控件的宽度和高度
        int width = this.getWidth();
        int height = this.getHeight();

        // 清除显示
        //g.clearRect(0, 0, width, height);

        // 背景色
        g.setColor(bgColor);
        g.fillRect(0, 0, width,height);

        /
        if(image != null)
        {
            int imgW = image.getWidth(null);
            int imgH = image.getHeight(null);

            // 使用  AfImageScaler 来计算
            MyImageScaler scaler = new MyImageScaler(imgW, imgH, width,height);

            // 根据缩放类型,来计算目标区域
            Rectangle fit = scaler.fitXY();
            if(scaleType == FIT_CENTER)
                fit = scaler.fitCenter();
            else if(scaleType == FIT_CENTER_INSIDE)
                fit = scaler.fitCenterInside();

            // 绘制
            g.drawImage(image, fit.x, fit.y, fit.width, fit.height,	null);
        }
    }

}

3、图片比例工具

// 图片缩放计算
//具体在哪放图片,通过计算得到适合的图片矩形
public class MyImageScaler
{
    // 输入参数
    private int imgW,imgH; // 图片的宽度、高度
    private Rectangle rect; // 要绘制的目标区域

    // imgW, imgH, 图片的宽度/高度
    // rect: 目标区域
    public MyImageScaler(int imgW, int imgH, Rectangle rect)
    {
        this.imgW = imgW;
        this.imgH = imgH;
        this.rect = rect;
    }
    public MyImageScaler(int imgW, int imgH, int dstW, int dstH)
    {
        this(imgW, imgH, new Rectangle(dstW, dstH));
    }

    // 拉伸显示,占满空间(比例可能失调)
    public Rectangle fitXY()
    {
        return this.rect;
    }

    // 居中显示,保持长宽比,且适合目标矩形(缩小显示)
    public Rectangle fitCenter()
    {
        int width = rect.width;
        int height = rect.height;

        int fitW = width;
        int fitH = width * imgH / imgW;
        if( fitH > height )
        {
            fitH = height;
            fitW = height * imgW / imgH;
        }
        int x = (width - fitW ) /2;
        int y = (height - fitH ) /2;

        // 结果
        return new Rectangle(rect.x + x, rect.y + y, fitW, fitH);
    }

    // 如果图片小于目标矩形,则直接居中显示
    // 如果图片大于目标矩形,则按fitCenter()缩放后显示
    public Rectangle fitCenterInside()
    {
        int width = rect.width;
        int height = rect.height;
        int fitW, fitH;

        if(imgW <= width && imgH <= height)
        {
            fitW = imgW;
            fitH = imgH;

            int x = (width - fitW ) /2;
            int y = (height - fitH ) /2;
            return new Rectangle(rect.x + x, rect.y + y, fitW, fitH);
        }
        else
        {
            return fitCenter();
        }
    }

}

 

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霓乤

谢谢支持,菜鸟会继续努力..

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值