You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Swing程序按钮切换求助:按钮2与按钮3点击互切

实现Java Swing按钮切换功能的解决方案

要满足初始显示button1和button2,点击button2执行功能后替换为button3,点击button3执行功能后换回button2的需求,只需对现有代码做以下几处修改:

核心改动说明

  1. 将按钮面板设为类成员:让buttonPanel成为PlayWithFace类的成员变量,这样在按钮的点击事件中可以动态修改其组件
  2. 修改按钮点击事件逻辑:在两个按钮的监听器中,执行完原有功能后,动态移除当前按钮并添加目标按钮,最后刷新面板

修改后的完整代码

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.swing.*;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.objdetect.CascadeClassifier;

class FaceArea {
    private String currentImage;

    FaceArea() {
        currentImage = "";
    }

    String getCurrentImage() {
        return currentImage;
    }

    void setCurrentImage(String imageName) {
        currentImage = imageName;
    }

    void FaceAreas(Graphics g, Rect[] faceAreas) {
        if (currentImage.equals("imageV1.jpg")) {
            V1(g, faceAreas);
        } else if (currentImage.equals("imageV2.jpg")) {
            V2(g, faceAreas);
        }
    }

    private void V1(Graphics g, Rect[] faceAreas) {
        g.setColor(Color.yellow);
        for (Rect rect : faceAreas) {
            g.drawRect((rect.x) / 2 - 20, rect.y / 2 + 400, rect.width / 3 + 20, rect.height / 3 + 20);
        }
    }

    private void V2(Graphics g, Rect[] faceAreas) {
        g.setColor(Color.yellow);
        for (Rect rect : faceAreas) {
            g.drawRect((rect.x - 10) / 2, rect.y / 2 + 400, rect.width / 3 + 25, rect.height / 3 + 25);
        }
    }

    void Text(Graphics g, JTextArea textArea) {
        if (currentImage.equals("message.txt")) {
            g.setColor(Color.blue);
            g.setFont(new Font("Arial", Font.PLAIN, 16));
            String[] lines = textArea.getText().split("\n");
            int y = 420;
            for (String line : lines) {
                g.drawString(line, 10, y);
                y += g.getFontMetrics().getHeight();
            }
        }
    }
}

public class PlayWithFace extends JFrame {

    BufferedImage bimage1, bimage2;
    Mat src1, src2;
    String FromCamera = "FromCamera.jpg";
    ArrayList<String> imageFiles;
    Iterator<String> imageIterator;
    String path = "/opt/homebrew/Cellar/opencv/4.8.1_1/share/opencv4/haarcascades/";
    String cascade = "haarcascade_frontalface_alt.xml";
    Rect[] faceArea1 = null;
    Rect[] faceArea2 = null;
    int count = 0;

    JButton button1, button2, button3;
    FaceArea faceArea;
    JTextArea textArea;
    private BufferedImage originalBimage1;
    JPanel buttonPanel; // 改为类成员变量

    public PlayWithFace() {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        setTitle("Play with Face");
        setSize(500, 760);
        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        textArea = new JTextArea();
        faceArea = new FaceArea();
        detect();
        
        repaint();
        
        button1 = new JButton("Next Image");
        button1.addActionListener(e -> loadNextImage());

        button2 = new JButton("Change Face");
        button2.addActionListener(e -> {
            // 执行原有功能
            changeFace();
            // 切换按钮:移除button2,添加button3
            buttonPanel.remove(button2);
            buttonPanel.add(button3);
            // 刷新面板布局
            buttonPanel.revalidate();
            buttonPanel.repaint();
        });

        button3 = new JButton("Return Face");
        button3.addActionListener(e -> {
            // 执行原有功能
            returnFace();
            // 切换按钮:移除button3,添加button2
            buttonPanel.remove(button3);
            buttonPanel.add(button2);
            // 刷新面板布局
            buttonPanel.revalidate();
            buttonPanel.repaint();
        });

        buttonPanel = new JPanel();
        buttonPanel.add(button1);
        buttonPanel.add(button2);

        setLayout(new BorderLayout());
        add(buttonPanel, BorderLayout.NORTH);

        setVisible(true);
    }
    
    private void Text(String filePath) {
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                content.append(line).append("\n");
            }
            textArea.setText(content.toString());
            faceArea.setCurrentImage("message.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadNextImage() {
        if (imageIterator.hasNext()) {
            String nextImage = imageIterator.next();
            if (nextImage.endsWith(".jpg") || nextImage.endsWith(".jpeg") || nextImage.endsWith(".png")) {
                src2 = Imgcodecs.imread(nextImage);
                bimage2 = matToBufferedImage(src2);
                faceArea2 = getArea(cascade, src2);
                faceArea.setCurrentImage(nextImage);
            } else if (nextImage.endsWith(".txt")) {
                Text(nextImage);
            }
            repaint();
        }
    }

    private void changeFace() {
        if (faceArea2 != null) {
            Rect[] faceArea2Copy = Arrays.copyOf(faceArea2, faceArea2.length);
            if (bimage1 != null && bimage2 != null) {
                Graphics2D g2d = bimage1.createGraphics();
                if (faceArea.getCurrentImage().equals("imageV1.jpg")) {
                    for (Rect rect : faceArea2Copy) {
                        BufferedImage facePart = bimage2.getSubimage(rect.x, rect.y, rect.width, rect.height);
                        g2d.drawImage(facePart, rect.x + 45, rect.y - 140,
                                rect.width + 360, rect.height + 390, this);
                    }
                } else if (faceArea.getCurrentImage().equals("imageV2.jpg")) {
                    for (Rect rect : faceArea2Copy) {
                        BufferedImage facePart = bimage2.getSubimage(rect.x, rect.y, rect.width, rect.height);
                        g2d.drawImage(facePart, rect.x + 305, rect.y - 30,
                                rect.width + 295, rect.height + 325, this);
                    }
                }

                g2d.dispose();
            }
            repaint();
        }
    }

    private void returnFace() {
        if (originalBimage1 != null) {
            // 恢复原始图像
            bimage1 = deepCopy(originalBimage1);
            faceArea1 = getArea(cascade, matFromBufferedImage(bimage1));
            repaint();
        }
    }

    public void paint(Graphics g) {
        if (bimage1 != null) {
            g.drawImage(bimage1, 10, 70, bimage1.getWidth() / 3, bimage1.getHeight() / 3, this);
        }

        if (bimage2 != null) {
            g.drawImage(bimage2, 10, 400, bimage2.getWidth() / 2 - 60, bimage2.getHeight() / 2 - 10, this);
        }

        if (faceArea1 != null) {
            g.setColor(Color.red);
            for (Rect rect : faceArea1) {
                g.drawRect((rect.x + 20) / 3, (rect.y + 60) / 2, rect.width / 3 + 10, rect.height / 3 + 20);
            }
        }

        if (faceArea2 != null) {
            faceArea.FaceAreas(g, faceArea2);
        }

        faceArea.Text(g, textArea);
    }

    private void detect() {
        src1 = Imgcodecs.imread(FromCamera);
        bimage1 = matToBufferedImage(src1);
        originalBimage1 = deepCopy(bimage1); // 保存原始图像的深拷贝
        faceArea1 = getArea(cascade, src1);

        imageFiles = new ArrayList<>();
        imageFiles.add("message.txt");
        imageFiles.add("imageV1.jpg");
        imageFiles.add("imageV2.jpg");
        imageIterator = imageFiles.iterator();
        loadNextImage();
    }

    private Rect[] getArea(String str, Mat src) {
        Rect[] area = null;
        CascadeClassifier faceDetector = new CascadeClassifier(path + str);
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(src, faceDetections);
        area = faceDetections.toArray();
        return area;
    }

    private BufferedImage matToBufferedImage(Mat matrix) {
        int cols = matrix.cols();
        int rows = matrix.rows();
        int elemSize = (int) matrix.elemSize();
        byte[] data = new byte[cols * rows * elemSize];
        int type;

        matrix.get(0, 0, data);

        switch (matrix.channels()) {
            case 1:
                type = BufferedImage.TYPE_BYTE_GRAY;
                break;
            case 3:
                type = BufferedImage.TYPE_3BYTE_BGR;
                byte b;
                for (int i = 0; i < data.length; i = i + 3) {
                    b = data[i];
                    data[i] = data[i + 2];
                    data[i + 2] = b;
                }
                break;
            default:
                return null;
        }

        BufferedImage out = new BufferedImage(cols, rows, type);
        out.getRaster().setDataElements(0, 0, cols, rows, data);
        return out;
    }

    private Mat matFromBufferedImage(BufferedImage image) {
        Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
        byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        mat.put(0, 0, data);
        return mat;
    }

    private BufferedImage deepCopy(BufferedImage bi) {
        ColorModel cm = bi.getColorModel();
        boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
        WritableRaster raster = bi.copyData(null);
        return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new PlayWithFace());
    }
}

改动细节解释

  • buttonPanel成员化:将原本在构造方法内声明的JPanel buttonPanel提升为类成员,确保按钮点击事件能访问并修改该面板的组件
  • 按钮切换逻辑:在button2和button3的监听器中,先执行原有业务逻辑(changeFace()/returnFace()),然后通过remove()移除当前按钮,add()添加目标按钮,最后调用revalidate()和repaint()刷新面板,确保界面及时更新

内容的提问来源于stack exchange,提问作者長衞哲弘

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:47:01