如何将动态背景图片加载到JPanel中?
我有一个秋千gui应用程序。我想输入一个图像路径,然后点击按钮将图像加载到jpanel中。问题是它不会被加载,但如果我添加扩展的jpanel,它可以在我插入jframe时加载图像,则图像可以正常加载。这是为什么?如何将动态背景图片加载到JPanel中?
相关的代码:
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;
}
}
调用类:
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
}
什么想法?我一直在为此工作两个小时。
要更新面板,您应该在面板的父级调用revalidate()方法,而不是在新面板上重新绘制(),因为您更改内容本身(面板)而不是图像。在你的情况下,它的内容窗格,哪些内容应该验证。
但它仍然没有,如果你问我更新面板内的图像的最佳方式......
你可以试试这个简单的例子(其更加简单和完美的作品):
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中图形的工作方式,则可以重新绘制整个面板)。
正如你所看到的,我甚至没有触摸面板本身 - 只是改变了图像源。
是的,你是对的。但getContentPane()。validate不能很好地工作,尽管图像显示出来了,但图像中还有一些额外的类似文本框的东西,不知道。如果首先添加一个面板,然后动态改变图像路径,这很好,就像你所建议的那样,我会采取第二个选项。谢谢。 – user1231111 2012-04-10 01:56:46
@AndrewThompson“如果你对原始代码有强烈的感受” - 不是真的,谢谢你的改变:) – 2012-04-10 11:01:45
不客气。 :) – 2012-04-10 11:41:36
请接受你的老问题的答案 - 如果他们帮助你。这会提高你回答这个问题的机会。 – 2012-04-09 14:27:17