我正在实现一个从文件加载并可以编辑它的 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/