Multiples JFrame无法正确重绘

时间:2014-05-22 23:10:15

标签: java swing jframe repaint

我正在为测试目的创建一个简单的应用程序,它分别显示几个JFrame,每个都包含一个图像。

问题在于它根据列表中的图像数显示了预期的JFrame数,但只有最后一个显示图像。所有其他的都是空的。

我已经进行了调试,并检查Buffered Image列表是否完全符合预期,所有对象都在那里,并且它们是彼此的副本,因为它是一个测试。

repaint调用(已经在各种地方尝试过)或ImgPanel子类有什么问题吗?这是我对可能出错的唯一猜测。

public class Main() extends JFrame{

   BufferedImage I;

   public void show(ArrayList<BufferedImage> images){
       int i = 0;
       for(BufferedImage b : images){
           this.I = b;

           Container c = getContentPane();
           c.setLayout(null);
           c.add(new ImgPanel());

           JFrame frame = new JFrame();
           frame.validate();
           frame.repaint();

           frame.setTitle("Execution: "+i);
           frame.getContentPane().add(c);
           frame.setSize(800,600);
           frame.setVisible(true);
           i++;
       }
   }

   public class ImgPanel extends JPanel {
       public imgPanel() { 
           setBounds(0, 0, 800,600);  
       }

       @Override
       public void paint(Graphics g) {
           super.paint(g);
           g.drawImage(I, 0, 0, this);
       }
   }

   public static void main(String[] args){
       //"d" is an Object Already declared
       ArrayList<BufferedImage> images = d.getImages();
       Main m = new Main();
       m.show(images);
   }
}

3 个答案:

答案 0 :(得分:4)

由于您的代码无法编译,我不确定问题出在哪里。此代码可靠地工作(坚如磐石)。在此GUI中,我倾向于将ImgPanel替换为JLabel,YMMV。

import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import java.net.URL;

public class Main {

   public void show(ArrayList<BufferedImage> images){
       int i = 0;
       for(BufferedImage b : images){

           JFrame frame = new JFrame("Execution: "+i);
           frame.add(new ImgPanel(b));
           frame.pack();
           frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
           frame.setLocationByPlatform(true);
           frame.setVisible(true);
           i++;
       }
   }

   public class ImgPanel extends JPanel {

       BufferedImage i;

       public ImgPanel(BufferedImage image) {
           i = image;
       }

       @Override
       public Dimension getPreferredSize() {
           return new Dimension(i.getWidth(), i.getHeight());
       }

       @Override
       public void paintComponent(Graphics g) {
           super.paintComponent(g);
           g.drawImage(i, 0, 0, this);
       }
   }

   public static void main(String[] args) throws Exception {
       final ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
       String[] urlStrings = {
           "http://i.stack.imgur.com/XZ4V5.jpg",
           "http://i.stack.imgur.com/7bI1Y.jpg",
           "http://i.stack.imgur.com/OVOg3.jpg",
           "http://i.stack.imgur.com/lxthA.jpg"
       };
       for (String s : urlStrings) {
           URL url = new URL(s);
           BufferedImage bi = ImageIO.read(url);
           images.add(bi);
       }
       Runnable r = new Runnable() {
           public void run() {
               Main m = new Main();
               m.show(images);
           }
       };
       SwingUtilities.invokeLater(r);
   }
}

答案 1 :(得分:4)

根据您的,不完整的代码示例和问题描述,我建议问题与您尝试将组件的单个实例添加到多个容器有关,例如......

Container c = getContentPane();
c.setLayout(null);
c.add(new ImgPanel());
//...
frame.getContentPane().add(c);

一个组件只能驻留在一个容器中,当一个组件被添加到一个新容器时,它首先从它的当前容器中移除(如果它有一个父容器)。

您可以通过将ImgPanel背景颜色设置为其他内容来测试,例如setBackgroundColor(Color.RED),唯一显示为红色的帧应该是最后一个...

  • 您应该避免null布局,在这种特定情况下,您可能不会考虑边框框架,这意味着内容区域将扩展到框架的可视区域之外。框架边框在不同的外观和感觉/平台上也有不同的尺寸
  • 通常鼓励paintComponent使用paint而不是JLabel因为它可以减少怪异的风险,并可能打破油漆链
  • 我会忽略使用{{1}}来完成此事更简单的事实

答案 2 :(得分:1)

使用JPanel时,请使用paintComponent(Graphics)

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