java学习--美颜相机Pro

本文介绍如何改进美颜相机应用,通过简化图片选择流程,添加多个按钮控制不同图像效果,并使用JPanel和ImageFilter类实现动态图像处理。读者将学习如何创建主窗体、定制面板布局和事件监听器,以提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.创建主窗体

2.面板JPanel 类.

 2.1.createPanel()

 2.2.initBtnPanel()

 2.3.创建中央面板以绘制图像

2.3.1.创建ImagePanel类

 2.3.2.initImgPanel()

3.ImageFilter类

4.监听器ImageProListener

5.实现效果

回顾上期美颜相机博客,我们已经实现了将图片地址输入文本框中后将所在地址图片绘画出来的功能。然而有人可能会觉得一个个字符将图片地址打入文本框中太累了,每次打开图片都要去获取图片地址不方便,而且按钮与绘图区域位置设定不方便。

 有没有什么方法能将打开图片的方式变得简单,就像我们下载时可以自由选择下载的位置那样,可以自由选择电脑上存在的图片打开;并且按钮的布局更加灵活,通过这篇博客我们完善美颜相机的功能。

1.创建主窗体

public void showUI(){
        JFrame jf=new JFrame();
        jf.setTitle("美颜相机");
        jf.setSize(1000,800);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLocationRelativeTo(null);
        //设置窗口布局为边界布局
        jf.setLayout(new BorderLayout());
        jf.setVisible(true);
}

2.面板JPanel 类.

JPanel是Java图形用户界面工具包Swing中的面板容器类,包含在javax.swing包中,是一种轻量级容器,可以加入到JFrame窗体中。JPanel默认的布局管理器是FlowLayout,其自身可以嵌套组合,在不同子容器中可包含其他组件,如JButton、JTextArea、JTextField等,功能是对窗体上的这些控件进行组合。

容器:可以存放其他组件

*窗体JFrame自己可以独立显示在屏幕上

*面板JPanel要加载到JFrame等高级容器上

 2.1.createPanel()

创建createPanel()方法实现创建面板对象并将面板对象添加到窗体中

 public JPanel createPanel(JFrame jf,Color color,int size,String border) {
        JPanel jp=new JPanel();
        jp.setBackground(color);
        jf.add(jp,border);
        jp.setPreferredSize(new Dimension(size,size));
        return jp;
    }

面板背景色为color,方位为border,常用的有SOUTH,NORTH,EAST,WEST

在窗体中下方添加面板

JPanel jp_s=createPanel(jf,Color.LIGHT_GRAY,100,BorderLayout.SOUTH);

多个面板

 2.2.initBtnPanel()

面板创建好了,可要知道面板是一个容器,里面不放东西发挥不了它的作用

接下来我们创建initBtnPanel()方法将按钮添加到面板上

    public void initBtnPanel(JPanel jp){
        String[] strs={"打开","撤回", "原图", "马赛克", "灰度", "二值化", "圆点马赛克", "反片", "轮廓化", "油画", "暖色调","冷色调"};
        for(int i=0;i<strs.length;i++){
            JButton btn =new JButton(strs[i]);
            btn.setBackground(Color.white);
            btn.addActionListener(lis);
            jp.add(btn);
        }
    }
initBtnPanel(jp_s);

lis为我们创建的监听器,用jp.add()将按钮添加到面板上

 2.3.创建中央面板以绘制图像

2.3.1.创建ImagePanel类

ImagePanel继承JPanel类

public class ImagePanel extends JPanel{
    ArrayList<BufferedImage> bfImgList;
    public void paint(Graphics g){
        super.paint(g);

        if(bfImgList.size()==0){
            return;
        }
        int index=bfImgList.size()-1;
        BufferedImage bfImg=bfImgList.get(index);
        g.drawImage(bfImg,100,80,null);
    }
}

BufferedImage是Java中的一个类,它继承自Image类。它是用于处理和操作图像的常用工具之

一。BufferedImage提供了一些方法来创建、修改和访问图像数据。BufferedImage将一幅图片加载

到内存中以便我们更好地对图像进行处理。

bufImgList中存储每幅加载的图片

paint()方法用来在面板上实时画最新一幅图,若bfImgList为空,则不执行

 2.3.2.initImgPanel()

public ImagePanel initImgPanel(JFrame jf,Color color){
        ImagePanel imagePanel=new ImagePanel();
        imagePanel.setBackground(color);
        jf.add(imagePanel);
        imagePanel.bfImgList=lis.bfImgList;//传递监听器中图像列表到ImagePanel中
        lis.imagePanel=imagePanel;
        return imagePanel;
    }

3.ImageFilter类

ImageFilter 类包含了不同的图像处理方法,用于生成具有不同效果的图像。每个方法都接受
一个包含图像像素的二维数组作为输入,并返回一个经过处理后的 BufferedImage 对象。
此外,该类还提供了从文件路径获取图像像素矩阵的方法。
public class ImageFilter {

    //原图
    public BufferedImage drawImage_01(int[][] imgArr) {
        //创建新的bufferedImage对象,用于绘制图像
        BufferedImage bfimg = new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
        //获取绘图上下文
        Graphics bg = bfimg.getGraphics();
        for (int i = 0; i < imgArr.length; i++) {
            for (int j = 0; j < imgArr[0].length; j++) {
                int rgb = imgArr[i][j];
                Color color = new Color(rgb);
                bg.setColor(color);
                bg.fillRect(i, j, 1, 1);
            }
        }
        //返回绘制好的缓存图像
        return bfimg;
    }

    //马赛克
    public BufferedImage drawImage_02(int[][] imgArr) {
        BufferedImage bfimg = new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
        Graphics bg = bfimg.getGraphics();
        for (int i = 0; i < imgArr.length; i += 3) {
            for (int j = 0; j < imgArr[0].length; j += 3) {
                int rgb = imgArr[i][j];
                Color color = new Color(rgb);
                bg.setColor(color);
                bg.fillRect(i, j, 3, 3);
            }
        }
        return bfimg;
    }
    
    //获取图片地址
    public int[][] getImagePixel(String imagePaths){
        File file=new File(imagePaths);
        BufferedImage buffImg=null;
        try {
            buffImg = ImageIO.read(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        int width=buffImg.getWidth();
        int height=buffImg.getHeight();
        int [][]imgArr=new int[width][height];
        for(int i=0;i<width;i++){
            for(int j=0;j<height;j++){
                imgArr[i][j]=buffImg.getRGB(i,j);
            }
        }
        return imgArr;
    }
}

 在此仅列举两种图像处理方法和获取图片地址的方法,有兴趣的可以参考上一篇博客

4.监听器ImageProListener

基本布局有了,接下来要将窗体对象中的按钮与具体的方法相关联,通过监听器来实现

public class ImageProListener implements ActionListener {
    Graphics g;
    int[][] imagePixel;
    int index;
    BufferedImage bfImg;//当前绘制的图像
    ArrayList<BufferedImage> bfImgList=new ArrayList<>();//存储图像的列表
    ImagePanel imagePanel;//图片显示面板
    ImageFilter imgFl=new ImageFilter();//创建图片处理器对象
    @Override
    public void actionPerformed(ActionEvent e) {
        String btnText=e.getActionCommand();//获取按钮文本
        System.out.println(btnText);

        if(btnText.equals("打开")){
            JFileChooser chooser=new JFileChooser();
            FileNameExtensionFilter filter=new FileNameExtensionFilter("JPG & PNG Images", "jpg", "png", "jpeg");
            chooser.setFileFilter(filter);
            int returnVal=chooser.showOpenDialog(null);
            if(returnVal==JFileChooser.APPROVE_OPTION){
                System.out.println("You chose to open this file"+chooser.getSelectedFile().getName());
                String path=chooser.getSelectedFile().getPath();
                imagePixel=imgFl.getImagePixel(path);
                bfImg=imgFl.drawImage_01(imagePixel);
                bfImgList.add(bfImg);
            }
        }

        if(imagePixel==null){
            JOptionPane.showMessageDialog(null,"请先选择一张图片");
        }

        if(btnText.equals("原图")){
            bfImg=imgFl.drawImage_01(imagePixel);
            bfImgList.add(bfImg);//将画好的图片缓存到图像列表中,方便撤回操作
        } else if (btnText.equals("马赛克")) {
            bfImg=imgFl.drawImage_02(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("灰度")) {
            bfImg=imgFl.drawImage_03(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("二值化")) {
            bfImg=imgFl.drawImage_04(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("圆点马赛克")) {
            bfImg=imgFl.drawImage_05(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("反片")) {
            bfImg=imgFl.drawImage_06(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("轮廓化")) {
            bfImg=imgFl.drawImage_07(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("油画")) {
            bfImg=imgFl.drawImage_08(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("暖色调")) {
            bfImg=imgFl.drawImage_09(imagePixel);
            bfImgList.add(bfImg);
        } else if (btnText.equals("冷色调")) {
            bfImg=imgFl.drawImage_10(imagePixel);
            bfImgList.add(bfImg);
        }else if(btnText.equals("撤回")){
            //如果图像列表中有图像记录,则将上一张图片记录画出
            if(bfImgList.size()>0){
                index=bfImgList.size()-1;//获取当前图片存储的位置
                bfImgList.remove(index);//将当前图片移除
            }else{
                JOptionPane.showMessageDialog(null,"无缓存记录,无法撤回");
            }
        }
        imagePanel.repaint();//重绘
    }

}

JFileChooser是Java中一个用于打开文件对话框的类,可以方便地选择文件

FileNameExtensionFilter是Java中一个用于过滤文件后缀的类,可以设置文件后缀过滤器。

FileNameExtensionFilter filter=new FileNameExtensionFilter("JPG & PNG Images", "jpg", "png", "jpeg");

该代码表示过滤后缀为jpg或png或jpeg的文件,同时描述文件类型为JPG & PNG Images。

5.实现效果

屏幕录制 2023-10-25 192425

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

在杭之舟

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值