如何动态加载背景图像到JPanel?

时间:2012-04-09 14:20:08

标签: image swing jpanel

我有一个摇摆gui应用程序。我想键入图像路径,然后单击按钮将图像加载到jpanel。问题是它不会被加载,但如果我添加扩展的jpanel,它能够在我查看jframe时加载图像,可以正常加载图像。那是为什么?

相关代码:

package com.xdg.graphic;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ImageLoader extends JPanel {
    private String imgPath;
    private BufferedImage image;


    public ImageLoader(String imgPath) {
        this.imgPath = imgPath;
        try {
            this.image=ImageIO.read(new File(imgPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void paint(Graphics g) {
        g.drawImage(image, 0, 0, null);
    }

    @Override
    protected void paintComponent(Graphics g) {
        g.drawImage(image, 0, 0, null);
    }

    public Dimension getPreferredSize() {
        if (image == null) {
             return new Dimension(100,100);
        } else {
           return new Dimension(image.getWidth(null), image.getHeight(null));
       }
    }

    public String getImgPath() {
        return imgPath;
    }

    public void setImgPath(String imgPath) {
        this.imgPath = imgPath;
    }



}

invoker类:​​

package com.xdg.image;

import com.xdg.graphic.ImageLoader;
import sun.awt.windows.ThemeReader;

import java.awt.*;

public class FrmImgCropper extends javax.swing.JFrame {
    private ImageLoader imageLoader;

    /** Creates new form FrmImgCropper */
    public FrmImgCropper() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    //GEN-BEGIN:initComponents
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jPanel2 = new javax.swing.JPanel();
        tfImagePath = new javax.swing.JTextField();
        btnPreview = new javax.swing.JButton();
        tfRatioW = new javax.swing.JTextField();
        tfRatioH = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        btnLoad = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        btnPreview.setText("Preview");

        jLabel1.setText(":");

        btnLoad.setText("Load");
        btnLoad.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnLoadActionPerformed(evt);
            }
        });

        jLabel2.setText("Image Path:");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(jPanel2Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(
                        jPanel2Layout
                                .createSequentialGroup()
                                .addGap(34, 34, 34)
                                .addComponent(tfRatioW, javax.swing.GroupLayout.PREFERRED_SIZE, 55,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jLabel1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(tfRatioH, javax.swing.GroupLayout.PREFERRED_SIZE, 53,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 123,
                                        Short.MAX_VALUE)
                                .addComponent(btnLoad, javax.swing.GroupLayout.PREFERRED_SIZE, 82,
                                        javax.swing.GroupLayout.PREFERRED_SIZE).addGap(46, 46, 46)
                                .addComponent(btnPreview).addGap(276, 276, 276))
                .addGroup(
                        jPanel2Layout.createSequentialGroup().addGap(66, 66, 66).addComponent(jLabel2)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(tfImagePath, javax.swing.GroupLayout.DEFAULT_SIZE, 593, Short.MAX_VALUE)
                                .addGap(29, 29, 29)));
        jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(
                        javax.swing.GroupLayout.Alignment.TRAILING,
                        jPanel2Layout
                                .createSequentialGroup()
                                .addContainerGap(20, Short.MAX_VALUE)
                                .addGroup(
                                        jPanel2Layout
                                                .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                                .addComponent(jLabel2)
                                                .addComponent(tfImagePath, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(
                                        jPanel2Layout
                                                .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                                .addComponent(jLabel1)
                                                .addComponent(tfRatioW, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addComponent(tfRatioH, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addComponent(btnPreview).addComponent(btnLoad)).addGap(20, 20, 20)));

        getContentPane().add(jPanel2, java.awt.BorderLayout.SOUTH);

        pack();
    }// </editor-fold>
    //GEN-END:initComponents

    private void btnLoadActionPerformed(java.awt.event.ActionEvent evt) {
        if (imageLoader == null) {
            imageLoader = new ImageLoader(tfImagePath.getText());
            imageLoader.setBackground(Color.green);

            getContentPane().add(imageLoader, BorderLayout.CENTER);
            getContentPane().repaint();
            this.repaint();//image does not show up this way dnamically
        } else {
            imageLoader.setImgPath(tfImagePath.getText());
            imageLoader.repaint();
        }

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {

                FrmImgCropper cropper = new FrmImgCropper();
                cropper.getContentPane().add(new ImageLoader("i:\\temp4\\car.jpg"));  //if I add the image loader here directly,image shows up
                cropper.setSize(800, 900);
                cropper.setVisible(true);
            }
        });
    }

    //GEN-BEGIN:variables
    // Variables declaration - do not modify
    private javax.swing.JButton btnLoad;
    private javax.swing.JButton btnPreview;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JTextField tfImagePath;
    private javax.swing.JTextField tfRatioH;
    private javax.swing.JTextField tfRatioW;
    // End of variables declaration//GEN-END:variables

}

任何想法?我已经工作了两个小时。

1 个答案:

答案 0 :(得分:1)

要更新面板,您应该在面板的父级上调用revalidate()方法,而不是在新面板上调用repaint(),因为您更改了内容本身(面板)而不是图像。在您的情况下,它的内容窗格,应该验证哪些内容。

但如果你问我,它仍然不是更新面板内图像的最佳方式...
你可以试试这个简单的例子(它更简单,效果很好):

private static BufferedImage image = null;

public static void main ( String[] args )
{
    final JFrame imageFrame = new JFrame ();
    imageFrame.setLayout ( new BorderLayout () );

    final JPanel panel = new JPanel ()
    {
        protected void paintComponent ( Graphics g )
        {
            super.paintComponent ( g );

            if ( image != null )
            {
                g.drawImage ( image, getWidth () / 2 - image.getWidth () / 2,
                        getHeight () / 2 - image.getHeight () / 2, this );
            }
        }
    };
    imageFrame.add ( panel, BorderLayout.CENTER );

    imageFrame.add ( new JButton ( "Load image" )
    {
        {
            addActionListener ( new ActionListener ()
            {
                public void actionPerformed ( ActionEvent e )
                {
                    JFileChooser fc = new JFileChooser ();
                    fc.setDialogType ( JFileChooser.OPEN_DIALOG );

                    if ( fc.showOpenDialog ( imageFrame ) == JFileChooser.APPROVE_OPTION )
                    {
                        try
                        {
                            image = ImageIO.read ( fc.getSelectedFile () );
                            panel.repaint ();
                        }
                        catch ( IOException e1 )
                        {
                            //
                        }
                    }
                }
            } );
        }
    }, BorderLayout.SOUTH );

    imageFrame.setSize ( 500, 500 );
    imageFrame.setLocationRelativeTo ( null );
    imageFrame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
    imageFrame.setVisible ( true );
}

如果您更改面板内的图像,则需要执行的唯一实际操作 - 重新绘制受影响的面板矩形(如果您不想深入了解Swing中的图形,则重新绘制整个面板)。 / p>

正如您所看到的,我甚至没有触摸面板本身 - 只是更改了图像源。