jPanel не обновляется, пока я не изменю размер окна приложения

У меня одна проблема с моей панелью jPanel. У меня есть кнопка, которая представляет PNG-изображение из ввода String (математическая формула), а затем перекрашивает старое изображение в jPanel. И вот проблема. Изображение было изменено, но jPanel не перерисовывается, пока я вручную не изменю размер окна приложения.

Похоже, панель не перерисовывается до тех пор, пока не изменится размер. Но я понятия не имею, как это сделать в этой кнопке.

Я пробовал это и this, но без изменений.

Кстати. Я использую GUI Builder в netbeans.

Мой код ... первая попытка:

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();

person cMe    schedule 10.05.2012    source источник
comment
При открытии окна панель окрашивается? Или его совсем не видно? Обратите внимание, что панель может иметь размер 0/0, если менеджер по расположению еще не рассчитал ее границы.   -  person Thomas    schedule 10.05.2012
comment
Можете ли вы проверить, не становится ли jPanel недействительной при добавлении изображения? Изменение размера вызывает вызов validateTree, и, следовательно, диспетчер компоновки проверяет его дочерние элементы.   -  person maress    schedule 10.05.2012
comment
Вызов revalidate (); перед repaint () ;?   -  person StanislavL    schedule 10.05.2012


Ответы (2)


Вы можете позаботиться об этом с помощью ветки перерисовки фона. Вы можете поместить это в конструктор вашего подкласса 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();
person FThompson    schedule 10.05.2012
comment
Это работает почти идеально. Изображение будет перерисовано, но старое изображение останется на заднем плане до тех пор, пока не будет изменен размер окна. - person cMe; 10.05.2012
comment
Как сказано в сообщении nIce cOw, вы не должны отменять метод paint вашей панели. Вам следует переместить код рисования компонента с paint на paintComponent. - person FThompson; 10.05.2012
comment
Оно живое! Отлично, спасибо большое, ребята. Я читал в jdoc, что лучше переопределить paintComponent(), но не думал, что это такая уж большая проблема. - person cMe; 10.05.2012

Вы переопределяете свой paint(...) метод, что на самом деле никоим образом не является хорошей стратегией, поскольку в Swing по возможности старайтесь переопределить ваш paintComponent(...) метод. Более того, я предполагаю, что вы могли упустить свой код внутри SwingUtilities.invokeLater (...). Попробуйте использовать этот обновленный код, поместите изображения рядом с файлами .class (внутри папки изображений), чтобы структура была такой:

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

person nIcE cOw    schedule 10.05.2012