在调整应用程序窗口大小之前,jPanel不会刷新

时间:2012-05-10 13:29:44

标签: java image swing jpanel paintcomponent

我的jPanel有一个问题。 我有一个按钮,其中PNG图像来自String输入(数学公式),然后它将重新绘制jPanel中的旧图像。问题出在那里。图像已更改,但jPanel不会重新绘制,直到我手动调整应用程序窗口的大小。

看起来Panel在重新调整大小之前不会重新绘制。但我不知道该怎么做那个按钮。

我尝试了thisthis但没有改变。

顺便说一句。我在netbeans中使用GUI Builder。

我的代码......第一次尝试:

public class ImagePanel extends JPanel {

   private String path;
   Image img;
   public ImagePanel() {
        try {
            //save path
            path = "Example5.png";
            //load image
            img = ImageIO.read(new File(path));
        } catch (IOException ex) {
        }
    }
   @Override
   public void paint(Graphics g) {
      //draw the image
      if (show) {
        try {
            if (img != null) {
                img = ImageIO.read(new File(path));
                g.drawImage(img, 0, 0, this);
            }
        } catch (IOException ex) {
        }
     } else {
        show = true;
     }
   }
}

并在Window类/按钮方法中:

   imagePanel = new ImagePanel();
   imagePanel.repaint();
   imagePanel.updateUI();

第二次尝试:

public class ImagePanel extends JPanel {

   private String path;
   Image img;
   ImagePanel(Image img) {
        this.img = img;
   }

   public void setImg(Image img) {
       this.img = img;
   }

   @Override
   public void paintComponent(Graphics g) {
       super.paintComponent(g);

       // Draw image centered in the middle of the panel
       g.drawImage(img, 0, 0, this);
   }

}

和按钮:

imagePanel.setImg(new ImageIcon("2.png").getImage());
imagePanel.repaint();

2 个答案:

答案 0 :(得分:5)

您正在覆盖paint(...)方法,这在任何方面都不是一个好策略,因为在Swing中尽可能尝试覆盖您的paintComponent(...)方法。此外,我猜你可能错过了将你的代码放在SwingUtilities.invokeLater(...)方法中。尝试使用你的更新代码,将图像放在你的.class文件旁边(图像文件夹里面),这样结构就是,< / p>

PanelTest.class      ImagePanel.class        image(Folder)
                                             |     |     |
                                         image1 image2  image3(and so on)

=============================================== ===================================

import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.swing.*;

public class PanelTest
{
    private URL[] url = new URL[5]; 
    private int counter = 0;
    private ImageIcon image;
    private JButton updateButton;

    public PanelTest()
    {
        try
        {
            for (int i = 0; i < 5; i++)
            {
                url[i] = getClass().getResource("/image/geek" + i + ".gif");
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("Panel Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        image = new ImageIcon(url[0]);
        final ImagePanel ip = new ImagePanel(image.getImage());
        updateButton = new JButton("UPDATE");
        updateButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                counter++;
                if (counter < 5)
                {
                    image = new ImageIcon(url[counter]);
                    ip.setImg(image.getImage());
                }
                else
                    counter = -1;
            }
        });

        frame.getContentPane().add(ip, BorderLayout.CENTER);
        frame.getContentPane().add(updateButton, BorderLayout.PAGE_END);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new PanelTest().createAndDisplayGUI();
            }
        });
    }
}
class ImagePanel extends JPanel {

   private String path;
   private Image img;
   ImagePanel(Image img) {
        this.img = img;
   }

   public void setImg(Image img) {
       this.img = img;
       // Added by me, so as to update the image
       // as a new Image is made available.
       repaint();
   }

   /*
    * Added by me, make this a customary
    * habbit to override this method too
    * as you override paintComponent(...)
    * method of the said JComponent.
    */
   @Override
   public Dimension getPreferredSize()
   {
       return (new Dimension(300, 300));    
   }

   @Override
   public void paintComponent(Graphics g) {
       super.paintComponent(g);

       // Clears the previously drawn image.     
       g.clearRect(0, 0, getWidth(), getHeight());  
       // Draw image centered in the middle of the panel
       g.drawImage(img, 0, 0, this);
   }

}

如果您也想要图像,那么它们就是

GEEK0 GEEK1 GEEK2 GEEK3 GEEK4

答案 1 :(得分:4)

您可以使用背景重绘线程来处理此问题。您可以将它放在JPanel子类的构造函数中。

Thread repainter = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) { // I recommend setting a condition for your panel being open/visible
            repaint();
            try {
                Thread.sleep(30);
            } catch (InterruptedException ignored) {
            }
        }
    }
});
repainter.setName("Panel repaint");
repainter.setPriority(Thread.MIN_PRIORITY);
repainter.start();