Java Swing程序按钮切换求助:按钮2与按钮3点击互切
实现Java Swing按钮切换功能的解决方案
要满足初始显示button1和button2,点击button2执行功能后替换为button3,点击button3执行功能后换回button2的需求,只需对现有代码做以下几处修改:
核心改动说明
- 将按钮面板设为类成员:让
buttonPanel成为PlayWithFace类的成员变量,这样在按钮的点击事件中可以动态修改其组件 - 修改按钮点击事件逻辑:在两个按钮的监听器中,执行完原有功能后,动态移除当前按钮并添加目标按钮,最后刷新面板
修改后的完整代码
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,提问作者長衞哲弘
相关产品推荐
相关产品推荐

