java - 在 Java Swing/Awt 中实现图像加载器

标签 java image swing

我正在实现一个从文件加载并可以编辑它的 Paint 应用程序。 但是我的 Openfile 函数无法正确运行,它会正确加载图像并更改边界,但不会在 Jpanel 中绘制它。

这是我的代码。

public class OpenSave extends JPanel{

private static final long serialVersionUID = 1L;

protected BufferedImage imagem;

public OpenSave() {}

public void open(JPanel panel) throws IOException {
    JFileChooser escolher = new JFileChooser();
    escolher.setCurrentDirectory(new File("."));

    escolher.setFileFilter(new javax.swing.filechooser.FileFilter() {
        public boolean accept(File f) {
            return f.getName().toLowerCase().endsWith(".jpg") || f.isDirectory();
    }
    public String getDescription() {
         return "Imagens JPG";
    }
    });

    escolher.setFileFilter(new javax.swing.filechooser.FileFilter() {
        public boolean accept(File f) {
            return f.getName().toLowerCase().endsWith(".png") || f.isDirectory();
        }
    public String getDescription(){
        return "Imagens PNG";
    }
    });


    JFrame frame = new JFrame();
    frame.setIconImage(Toolkit.getDefaultToolkit().getImage(OpenSave.class.getResource("/javax/swing/plaf/metal/icons/ocean/directory.gif")));
    int r = escolher.showOpenDialog(frame);
    if (r == JFileChooser.APPROVE_OPTION) {
        imagem = ImageIO.read(new File(escolher.getSelectedFile().getAbsolutePath()));
        panel.setBounds(77, 13, imagem.getWidth(this), imagem.getHeight(this));
    }
  }


@Override
public void paintComponent(Graphics g) {          
    super.paintComponent(g);                         
    g.drawImage(imagem, 0, 0, this);
    repaint();
}
}

有了这个,我可以正确保存和加载,但加载的图像不会进入我的 JPanel 面板。

这里是简化的主类。

    private JPanel contentPane;
    private Jpanel panel;

    public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                TelaMain frame = new TelaMain();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    }

    public TelaMain() {

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 600, 400);

    JMenuBar menuBar = new JMenuBar();
    menuBar.setFocusTraversalKeysEnabled(true);
    setJMenuBar(menuBar);

    JMenu mnArchive = new JMenu("Archive");
    menuBar.add(mnArchive);
    JMenuItem mntmOpen = new JMenuItem("Open");
    mnArquivo.add(mntmOpen);

    panel = new JPanel();
    panel.setAutoscrolls(true);
    panel.setBorder(new LineBorder(new Color(0, 0, 0)));
    panel.setBackground(Color.WHITE);
    panel.setBounds(77, 13, 498, 307);
    contentPane.add(panel);

    mntmAbrir.addActionListener(
        new ActionListener() {
            public void actionPerformed(ActionEvent abrir) {
                    OpenSave a = new OpenSave();
                    try {
                        a.open(panel);
                        a.repaint();

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    );

我愿意接受针对我的问题的任何其他编辑建议。

最佳答案

你的代码看起来很困惑。具体来说:

  • 您创建了一个 JFrame 但从未显示它,也许只是将其用作文件选择器的参数?
  • 您将 JPanel 传递到 open 方法中,只是为了更改其大小,但您不对其执行任何其他操作。
  • 我有一种感觉,您认为 JPanel 中传递的内容会以某种方式获得您正在阅读的图像,但如果是这样,您就错了。
  • 该图像可能会显示在 OpenSave JPanel 中,但我们永远不会知道,因为我们从未见过您将其添加到任何顶级窗口(例如 JFrame)中 - 因此您当前的代码给我们提供了关于您的内容的不完整图片正在做。
  • 您的paintComponent方法很危险,因为它尝试在OpenSave JPanel中绘制图像,而不首先检查图像是否为空。如果当前没有可用图像,则代码可能会抛出 NullPointerException。
  • 您使用 setBounds(...) 是一件危险的事情。虽然 null 布局和 setBounds() 对于 Swing 新手来说似乎是创建复杂 GUI 的最简单、最好的方法,但创建的 Swing GUI 越多,使用它们时遇到的困难就越严重。当 GUI 调整大小时,它们不会调整组件的大小,它们是增强或维护的皇家女巫,当放置在滚动 Pane 中时,它们会完全失败,在所有平台或与原始分辨率不同的屏幕分辨率上查看时,它们看起来非常糟糕.

建议:

  • 确保将 OpenSave JPanel 放入显示的 JFrame
  • 在其paintComponent方法中,仅在图像不为空时绘制图像。换句话说,在 if block 中检查 null 并仅绘制 if (imagem != null) {}
  • 向我们展示您的其余相关代码
  • 将当前显示的 JFrame 传递到 JFileChooser,而不是未显示的 JFrame。
  • 让您的 OpenSave JPanel 覆盖 getPreferredSize,并将该大小设为它所保存的图像的大小。
  • 就我个人而言,我会将图像文件打开和保存代码与 View 代码(GUI 代码)分开。

示例的部分内容:

public void setImagem(BufferedImage imagem) {
    this.imagem = imagem;
    repaint();
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (imagem != null) {
        g.drawImage(imagem, 0, 0, this);
    }
}

@Override
public Dimension getPreferredSize() {
    Dimension sz = super.getPreferredSize();
    if (imagem != null) {
        sz = new Dimension(imagem.getWidth(), imagem.getHeight());
    }
    return sz;
}

private static void createAndShowGui() {
    MyOpenSave openSave = new MyOpenSave();

    JFrame frame = new JFrame("MyOpenSave");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(openSave);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> createAndShowGui());
}
<小时/>

更完整的示例:

TestOpenSave.java——“驱动程序”类

public class TestOpenSave {

    private static void createAndShowGui() {
        OpenSave openSave = new OpenSave();
        JFrame frame = new JFrame("OpenSave");

        JPanel btnPanel = new JPanel();
        btnPanel.add(new JButton(new GetImageAction("Open Image", frame, openSave)));

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(openSave);
        frame.add(btnPanel, BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

OpenSave.java,显示图像的“ View ”类

@SuppressWarnings("serial")
public class OpenSave extends JPanel {
    private BufferedImage imagem;

    public void setImagem(BufferedImage imagem) {
        this.imagem = imagem;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (imagem != null) {
            g.drawImage(imagem, 0, 0, this);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension sz = super.getPreferredSize();
        if (imagem != null) {
            sz = new Dimension(imagem.getWidth(), imagem.getHeight());
        }
        return sz;
    }
}

GetImageAction 文件加载类或“ Controller ”类。请注意,它与图像显示或“ View 类”是分开的

@SuppressWarnings("serial")
public class GetImageAction extends AbstractAction {
    private JFrame myFrame;
    private OpenSave openSave;

    public GetImageAction(String name, JFrame myFrame, OpenSave openSave) {
        super(name);
        this.myFrame = myFrame;
        this.openSave = openSave;
        int mnemonic = (int) name.charAt(0);
        putValue(MNEMONIC_KEY, mnemonic);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JFileChooser escolher = new JFileChooser();
        escolher.setMultiSelectionEnabled(false);
        escolher.setCurrentDirectory(new File("."));
        escolher.setFileFilter(new FileFilter() {

            @Override
            public String getDescription() {
                return "Imagens JPG and PNG";
            }

            @Override
            public boolean accept(File f) {
                String ext = f.getName().toLowerCase();
                if (f.isDirectory() || ext.endsWith(".jpg") || ext.endsWith(".png")) {
                    return true;
                }
                return false;
            }
        });
        int reply = escolher.showOpenDialog(myFrame);
        if (reply == JFileChooser.APPROVE_OPTION) {
            try {
                BufferedImage img = ImageIO.read(escolher.getSelectedFile());
                openSave.setImagem(img);
                myFrame.pack();
                myFrame.setLocationRelativeTo(null);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
}

关于java - 在 Java Swing/Awt 中实现图像加载器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43313687/

相关文章:

java - 使用 Tab 键从 JTextArea 移动焦点

java - 添加项目时 JComboBox 错误

java - android - 回调函数 - 现在显示对话框

java - 不使用 Spring 时出现 Spring 异常

html - 使用css使链接图像旋转90度

Java javax.swing.Timer 在新线程上运行吗?

Java 全局命名空间访问

html - 我的绝对图像需要响应

jquery - 使用 jQuery 切换图像 src

java - 无法在硬编码 java 应用程序中的 jFrame 之间进行更改?