繁体   English   中英

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

[英]Implementing a Image loader in Java Swing/Awt

我正在实现从文件加载并可以对其进行编辑的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传递到您的开放方法中,只是为了更改其大小,但对它不执行任何其他操作。
  • 我觉得您认为通过JPanel传递的图像会以某种方式获取您正在阅读的图像,但是如果是这样,那您就错了。
  • 该图像可能显示在OpenSave JPanel内,但是我们不知道,因为我们从未看到您将其添加到任何顶级窗口(例如JFrame)中-因此,您当前的代码不完整地显示了您的操作。
  • 您的paintComponent方法很危险,因为它试图在OpenSave JPanel中绘制图像,而不先检查图像是否为空。 如果当前没有可用的图像,这将使代码有引发NullPointerException的风险。
  • 您正在使用setBounds(...)做一件危险的事情。 尽管null布局和setBounds()似乎是Swing新手喜欢创建复杂GUI的最简单和最佳方法,但您创建的Swing GUI越多,使用它们时将遇到的困难就越大。 当GUI调整大小时,它们不会重新调整组件的大小;它们是需要增强或维护的皇家女巫;放置在滚动窗格中时,它们会完全失败;在所有平台或与原始分辨率不同的屏幕分辨率下查看时,它们看起来都是令人毛骨悚然的。

建议:

  • 确保将OpenSave JPanel放入显示的JFrame中
  • 在其paintComponent方法内,仅绘制不为null的图像。 换句话说,在if块中检查null,仅绘制if (imagem != null) {}
  • 向我们展示您其余的相关代码
  • 将当前显示的JFrame传递给JFileChooser,而不是未显示的JFrame。
  • 让您的OpenSave JPanel覆盖getPreferredSize,并使其大小成为其所持有图像的大小。
  • 我本人将打开和保存图像文件的代码与视图代码(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,显示图像的“视图”类

@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文件加载类或“控制器”类。 请注意,它与图像显示或“视图类”是分开的

@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();
            }
        }
    }
}

我不确定,但是问题可能是初始化JFrame时没有包含frame.add(this) ,这告诉程序在类中使用paint方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM