使用 JFrame 中的按钮将图像重新绘制到现有的 JPanel?

Repaint Image to existing JPanel with Button in JFrame?

我正在尝试将图像重新绘制到现有的 JPanel,这是我在单击按钮时通过在 JFrame 中拖放创建的。

代码如下:

package photo;


import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.event.ActionListener;


import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;


public class ImageFrame extends javax.swing.JFrame {

  public ImageFrame() {

      initComponents();

   }

public class ImagePanel extends JPanel{

    public BufferedImage image;

    public ImagePanel() {
       try {                
         image = ImageIO.read(new File("Vampire-full.jpg"));
       } catch (IOException ex) {
            // handle exception...
       }
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);      
    }

}      


    @Override
    public Component add(Component cmpnt) {
        return super.add(cmpnt); //To change body of generated methods, choose Tools | Templates.
    }



    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        Image123 = new javax.swing.JPanel();
        Import = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout Image123Layout = new javax.swing.GroupLayout(Image123);
        Image123.setLayout(Image123Layout);
        Image123Layout.setHorizontalGroup(
            Image123Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 473, Short.MAX_VALUE)
        );
        Image123Layout.setVerticalGroup(
            Image123Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 327, Short.MAX_VALUE)
        );

        Import.setText("Import");
        Import.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ImportActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(Image123, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(85, 85, 85)
                .addComponent(Import)
                .addGap(0, 24, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(Image123, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(Import)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>                        

    private void ImportActionPerformed(java.awt.event.ActionEvent evt) {                                       
       Image123.repaint();

    }                                      


    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ImageFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ImageFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ImageFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ImageFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
               // new ImageFrame().setVisible(true);
                new ImageFrame().setVisible(true);

            }

        });
    }





    // Variables declaration - do not modify                     
    private javax.swing.JPanel Image123;
    private javax.swing.JButton Import;
    // End of variables declaration                   



}

但是当我单击按钮时 JPanel 不会显示任何内容。 我已经通过用鼠标拖动它创建了 JPanel (Image123) Size。 如何解决这个问题?

抱歉,如果这个问题看起来很愚蠢。我只是想学习,需要指导如何去做。

根据您的问题和意见,我可以说您不想使用除 JPanel 之外的任何其他 class 来显示您的图像。让我们解释一下如何利用 JPanel 来减轻您对 ImagePanel 的担忧。

据我所知,当您想在 JPanel 中显示图像时,您没有太多选择,您应该在面板上绘制该图像。为此,您应该获取 JPanelGraphics 对象,以便能够在该面板上绘制图像或文本等。然后通过阅读 JPanel 的方法签名,您可以看到一些方法将该图形对象作为其输入参数,其中之一是 void paintComponent(Graphics g)。正如您可以从它的名字推断的那样,它负责绘制面板上要显示的任何内容。因此,通过覆盖它并使用 graphics 对象绘制我们的自定义图像,我们可以实现目标。

您在 Internet 上找到的 ImagePanel class 正在做您需要做的事情,因为当我们想要覆盖 JPanel 中的方法时,唯一的方法是扩展JPanel 这就是 ImagePanel 所做的。所以我不明白你想避免使用 ImagePanel 的原因是什么,因为它只不过是一个带有重写方法 paintComponentJPanel。因此,为了使您的代码正常工作,您应该像这样更改它:

private void initComponents() {

    Image123 = new ImagePanel();

    // ... your other codes ...
}

但如果你坚持不命名它ImagePanel,你可以通过内联方式覆盖它来实现。因此,在实例化 Image123 = new JPanel();initComponents() 中,您应该这样更改它:

private void initComponents() {

    Image123 = new JPanel() {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); // Let the panel do whatever it was doing before.

            BufferedImage image = null;             
            try {                
                image = ImageIO.read(new File("Vampire-full.jpg"));
            } catch (IOException ex) {
                   // handle exception...
            }

            g.drawImage(image, 0, 0, null);      
        }
    };
    // ... your other codes ...
}

如您所见,这些代码与您在 ImagePanel 中使用的代码相同,这里唯一改变的是名称,我可以说有一个命名的 class 来完成这项工作更多比上面的内联实现更优雅。现在您可以选择选择哪一个。

一旦你明白了,你应该知道paintComponent是一个在第一次创建面板时调用了很多次的方法,每次调整框架大小时,iconify/deiconify等.phases 和加载 paintComponent 中的图像是不好的。因此,您要么按照 ImagePanel 中的做法进行操作,要么将该图像加载到仅加载一次的位置。

希望这会有所帮助。