鼠标悬停前按钮不可见

Button not visible until mouse hovering

我是 java 的新人。我搜索了这个问题并找到了一些解决方案。但我没有得到任何改进。你们能告诉我我的代码有什么问题吗? 该程序将图像转换为 base64 字符串并解码为图像。也可以将字符串保存到文件中。 问题是第一个按钮在 运行 之后可见。但其他两个按钮在鼠标悬停之前不可见。

这是我的完整代码:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;

public class ImageConverter extends JFrame implements ActionListener {

JPanel jp = new JPanel();
JFileChooser directory = new JFileChooser();
JFileChooser fileChooser = new JFileChooser();
File selectedFile = null;
BufferedImage img;
FileInputStream in;
String imgstr;

JLabel imageLabel = new JLabel();

public ImageConverter() {
    super("Image Converter");

    // create Panel
    jp = new JPanel();
    setLayout(new FlowLayout());
    setBackground(Color.white);

    add(jp);

    JButton encode = new JButton("Encode");
    JButton decode = new JButton("Decode");
    JButton save = new JButton("Save Code");

    jp.add(encode);
    jp.add(decode);
    jp.add(save);


    encode.addActionListener(this);
    decode.addActionListener(this);
    save.addActionListener(this);

}

public void actionPerformed(ActionEvent e) {
    if (e.getActionCommand().equals("Encode")) {
        File selectedFile = null;
        fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            selectedFile = fileChooser.getSelectedFile();
            System.out.println("Selected file: " + selectedFile.getAbsolutePath());
            try {
                img = ImageIO.read(selectedFile);
            } catch (IOException ie) {
                // TODO Auto-generated catch block
                ie.printStackTrace();
            }
            repaint();
            imgstr = encodeToString(img, getFileExtension(selectedFile));
            System.out.println(imgstr);
        }
    } else if (e.getActionCommand().equals("Decode")) {
        File selectedFile = null;
        String code = "";
        fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            selectedFile = fileChooser.getSelectedFile();
            System.out.println("Selected file: " + selectedFile.getAbsolutePath());
            try {

                code = new Scanner(new File(selectedFile.getAbsolutePath())).useDelimiter("\Z").next();
            } catch (IOException ie) {
                // TODO Auto-generated catch block
                ie.printStackTrace();
            }
            System.out.println(code);
            img = decodeToImage(code);
            repaint();
        }

    } else {
        directory.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        directory.showOpenDialog(null);
        System.out.println(directory.getCurrentDirectory());
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(directory.getCurrentDirectory() + "/code.txt"));
            writer.write(imgstr);

        } catch (IOException ex) {
        } finally {
            try {
                if (writer != null)
                    writer.close();
            } catch (IOException ex) {
              ie.printStackTrace();
            }
        }

    }

}

public void paint(Graphics g) {
    g.drawImage(img, 50, 100, 450, 450, null);
}

public static BufferedImage decodeToImage(String imageString) {

    BufferedImage image = null;
    byte[] imageByte;
    try {
        imageByte = Base64.getDecoder().decode(imageString);
        ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
        image = ImageIO.read(bis);
        bis.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return image;
}

public static String encodeToString(BufferedImage image, String type) {
    String imageString = null;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    try {
        ImageIO.write(image, type, bos);

        byte[] imageBytes = bos.toByteArray();

        imageString = Base64.getEncoder().encodeToString(imageBytes);

        bos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return imageString;
}

private static String getFileExtension(File file) {
    String fileName = file.getName();
    if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0)
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    else
        return "";
}

public static void main(String Args[]) {
    ImageConverter frame = new ImageConverter();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    frame.setSize(600, 600);
    frame.setVisible(true);
}

}

PS: 请忽略我糟糕的英语和编码规范。

这是您遇到的问题之一:

public void paint(Graphics g) {
    g.drawImage(img, 50, 100, 450, 450, null);
}

您没有调用 super 的绘制方法,super.paint(g); 从而打破了绘制链,阻止了容器绘制其子项(按钮)。但话虽如此,您永远不应该重写 JFrame 的 paint 方法,您几乎应该总是在 JPanel 的 paintComponent 重写方法中绘制,再次在重写中调用 super 的方法。

其他问题:

  • 一定要在 Swing 事件线程上启动 GUI,方法是将启动代码放在 Runnable 中并将其传递到 SwingUtilities.invokeLater(...)
  • 在后台线程上执行任何长运行代码,例如使用 SwingWorker。