简体   繁体   中英

Repaint Image to existing JPanel with Button in JFrame?

I'm trying to repaint an image to existing JPanel which i created by drag and drop in JFrame when the button clicked.

Here's the code:

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                   



}

But the JPanel won't show anything when i clicked the button. I already created the JPanel (Image123) Size by dragging it with mouse. How to fix this?

Sorry if the question looks stupid. I'm just trying to learn and need guide how to do it.

Based on your question and your comments I can say you don't want to use any other class than the JPanel to show your image. Let's explain a bit about drawing on JPanel to lower your worries about ImagePanel .

As far as I know when you want to show an image in a JPanel you have not many choices and you should draw that image on your panel. To do that you should get the Graphics object of that JPanel in order to be able to paint your image or text etc. on that panel. Then by reading the method signatures of JPanel you can see some method have that graphics object as their input argument one of which is void paintComponent(Graphics g) . As you can infer from its name it is responsible for painting whatever is going to be shown on the panel. So by overriding it and painting our custom image using the graphics object we can achieve the goal.

The ImagePanel class you've found on internet is doing exactly what you need to do because when we want to override a method from JPanel the only way is to extend JPanel and that's what ImagePanel does. So I don't get what's the reason you want to avoid using ImagePanel since it is nothing but a JPanel with an overrided method paintComponent . So to make your code works you should change it like this:

private void initComponents() {

    Image123 = new ImagePanel();

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

But if you insist on not naming it ImagePanel , you can do it by overriding it in an inline way. So in your initComponents() where you are instantiating your Image123 = new JPanel(); you should change it this way:

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 ...
}

As you can see these are the same codes you had it in ImagePanel and the only thing changed here is the name and I can tell having a named class for doing this job is more elegant than the above inline implementation. Now it's your choice to pick which one.

Once you got the idea, you should know that paintComponent is a method that is called so many times during the first creation of the panel, every time you resize the frame, iconify/deiconify etc. phases and loading that image inside the paintComponent is bad. So either you should do as done in ImagePanel or to load that image in a place that is being loaded only once.

Hope this would be helpful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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