在Java

时间:2016-02-10 16:48:57

标签: java image exception loading

我在加载图片文件时遇到问题。 有2个案例,我已经过测试。问题仅出现在第一个问题中。在这两种情况下,JDialog-window显示a 缩小图像。 300ms后,该窗口自动关闭(ImageDialog和CardPrinter的构造函数中有一个计时器;这仅用于调试)。 在生产版本中,程序必须能够在JDialog中加载30-40个图像(逐个)。用户键入一些文本,然后单击按钮以显示下一个图像。 要加载图像,我在两种情况下都使用ImageIO.read()。或者我使用CMYKJPEGImage(http://www.randelshofer.ch/blog/2011/08/reading-cmyk-jpeg-images-with-java-imageio/) 但它也产生了例外。 在Main中有myTimer,用图像文件连续打开JDialog(应该通过设置变量pathtofiles,使用绝对路径调用listFilesRecurse())。

案例1) 使用覆盖布局管理器(Main.java,CardPrinter.java,IDCardLayout.java)在JDialog中加载图像。 为此,来自' CardPrinter的行cp = null;'到' cp.dispose();'在Main.java中必须取消注释。棘手的部分是addIDCard()@ CardPrinter。 这将是建立的布局。在调用此paintComponent()@ IDCardLayout之后,如果应该实现对话窗口的内容。 看来,加载的图像不会被破坏,并且内存已满(在Window的Taskmanager中可以看到内存使用情况)。

案例2) 在没有布局管理器的JDialog中加载图像(Main.java,ImageDialog.java)。 (取消注释行' mn.showDialog(mn.frame,file);')。 工作完美。没有例外!

函数ImageIO.read()应该没问题,因为在2.情况下,没有错误(即使代码运行20分钟)。 奇怪的是,在第一种情况下,布局管理器似乎阻止GC卸载未使用的图像......
1.case中的问题应该是CTR @ CardPrinter和addIDCard()@ CardPrinter。在CTR中我使用OverlayLayout。在2.case中,根本没有Layoutmanager。
Java版本是:Windows7 SP1上的1.7.0_80。
有人可以帮帮我吗?

提前谢谢你, 丹尼尔

  

例外情况:

  线程中的异常" AWT-EventQueue-0" java.lang.OutOfMemoryError:Java堆空间       at java.awt.image.DataBufferByte。(DataBufferByte.java:92)       at java.awt.image.ComponentSampleModel.createDataBuffer(ComponentSampleModel.java:415)       在java.awt.image.Raster.createWritableRaster(Raster.java:941)       在javax.imageio.ImageTypeSpecifier.createBufferedImage(ImageTypeSpecifier.java:1073)       在javax.imageio.ImageReader.getDestination(ImageReader.java:2896)       at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1066)       at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1034)       在javax.imageio.ImageIO.read(ImageIO.java:1448)       在javax.imageio.ImageIO.read(ImageIO.java:1308)       在test.IDCardLayout.loadPicture(IDCardLayout.java:128)       at test.CardPrinter.addIDCard(CardPrinter.java:142)       在test.CardPrinter。(CardPrinter.java:62)       at test.CardPrinter.createDialog(CardPrinter.java:91)       在test.Main $ 1.actionPerformed(Main.java:69)       在javax.swing.Timer.fireActionPerformed(Timer.java:312)       在javax.swing.Timer $ DoPostEvent.run(Timer.java:244)       在java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)       at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:745)       at java.awt.EventQueue.access $ 300(EventQueue.java:103)       at java.awt.EventQueue $ 3.run(EventQueue.java:706)       at java.awt.EventQueue $ 3.run(EventQueue.java:704)       at java.security.AccessController.doPrivileged(Native Method)       at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:76)       at java.awt.EventQueue.dispatchEvent(EventQueue.java:715)       at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)       at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)       at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)       at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

package test;
/*Main.java*/


import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;


public class Main {
    JFrame frame;


    //list files recursively, using a filter (pattern). If pattern=*, all files will be listed.
    public static void listFilesRecurse(String fullpath, String pattern[], Vector<File> foundFiles) throws IOException {
        File dir = new File(fullpath);
        File list[] = dir.listFiles();
        for(File f: list) {
            if( !f.isDirectory() ) {
                for(String pt: pattern) {
                    if(pt.equals("*")) {
                        foundFiles.add(f);
                        break;
                    }
                    else if( f.getAbsolutePath().toUpperCase().endsWith(pt.toUpperCase()) ) {
                        foundFiles.add(f);
                        break;
                    }
                }
            } else {
                listFilesRecurse(f.getAbsolutePath(), pattern, foundFiles);
            }
        }
    }


public static void main(String[] args) {
    final Main mn = new Main();
    final String pathtofiles = "\\path\\to\\files\\";

    ActionListener task = new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            Vector<File> list = new Vector<File>();
            System.out.println("\nListing files ...");
            try {
                listFilesRecurse(pathtofiles, new String[]{"jpg", "png", "jpeg"}, list);
            } catch (IOException e) {
                e.printStackTrace();
            }
            for(int index=0; index<list.size(); index++) {
                String file = list.get(index).getAbsolutePath();
                System.out.println("\nLoading image - " + index + ": " + file);

                //mn.showDialog(mn.frame, file);


                CardPrinter cp=null;
                try {
                    cp = CardPrinter.createDialog(mn.frame, "Max",
                                                  "Muster", "1122", "12345678", "01/2018", file);
                } catch (Exception e) {
                    e.printStackTrace();
                    continue; //break;  //return;
                }
                cp.setVisible(true);
                cp.dispose();
            }
        }
    };
    final Timer myTimer = new Timer(100,  task);
    myTimer.setRepeats(true);


    JFrame frame = new JFrame("JFrame Example");
    mn.frame = frame;

    JPanel panel = new JPanel(); 
    panel.setLayout(new FlowLayout());

    JLabel label = new JLabel("This is a label!"); 
    JButton button = new JButton(); 

    button.setText("Press me");
    button.addActionListener( new ActionListener() {
        public void actionPerformed(ActionEvent actionEvent) {
            myTimer.start();
        }
    });

    panel.add(label);
    panel.add(button);
    frame.add(panel);
    frame.setSize(300, 300);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}


//opens the dialog that display an image (file).
public void showDialog(JFrame fr, String file) {
    ImageDialog imgd = new ImageDialog(fr, "Testdialog", file);
    imgd.setSize(300, 300);
    imgd.setModal(true);
    imgd.setLocation(250, 250);
    imgd.setVisible(true);
}

}
package test;
/*ImageDialog.java*/

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.Timer;

import org.monte.cmykdemo.CMYKJPEGImage;


public class ImageDialog extends JDialog {
    String file;


    public ImageDialog(JFrame frame, String title, String file) {
        super(frame, title);
        this.file = file;

        //######For debugging only. This will close the dialog window after 300 ms (by calling ImageDialog.this.setVisible(false);).
        ActionListener task = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                ImageDialog.this.dispose();
            }
        };
        Timer cl = new Timer(300, task);
        cl.start();
        //#######
    }


    //renders the picture on screen.
    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        setRenderingHints(g2d);

        BufferedImage img=null;
        try {
            img = loadPicture(this.file);
        } catch (IOException e) {
            e.printStackTrace();
        }

        g2d.setColor(Color.BLUE);
        g2d.drawRect(0, 0, this.getWidth(), this.getHeight());
        g2d.drawImage(img, 10, 10,  80,  80,  null, null);
    }


    void setRenderingHints(Graphics2D g2) {
        g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
        g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
        g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
    }

    public static BufferedImage loadPicture(String fullpath) throws IOException {
        System.out.println("\nloadPicture(): " + fullpath);
        //BufferedImage img = (BufferedImage) CMYKJPEGImage.loadImage( fullpath );
        BufferedImage img = (BufferedImage) ImageIO.read( new File(fullpath) );
        return img;
    }
}
package test;
/*CardPrinter.java*/

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.OverlayLayout;
import javax.swing.Timer;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.BorderFactory;
import javax.swing.JButton;


public class CardPrinter extends JDialog /*implements Printable*/ {
  protected JPanel jp;
  protected JTextField tx;
  protected JLabel lblCounter;
  protected IDCardLayout idcard;
  protected String vorname, nachname, id, gueltig, bild;

  protected String chipid;


  protected CardPrinter(Window owner, String vorname, String nachname, String id, String chipid,
                        String gueltig, String bild /*, DataReceiver drv*/) throws IOException {
      super((Window)owner, "Assign_ChipID_DialogObject");
      this.bild = bild;
      //this.datareceiver = drv;
      setTitle("Assign ID");
      setModalityType(JDialog.DEFAULT_MODALITY_TYPE);
      setResizable(false);

      jp = new JPanel();
      jp.setLayout(null);
      jp.setOpaque(false);

      addIDCard();
      //setupButtons();

      //setSize(this.getPreferredSize().width, this.getPreferredSize().height);
      setSize(250, 250); //+++
      setLocation(300, 300); //+++

      //Overlay components: tx overlaps idcard
      JPanel cnt = new JPanel();
      cnt.setLayout(new OverlayLayout(cnt));
      cnt.add(jp);
      getContentPane().add(cnt);

      setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);


      //######For debugging only. This will close the dialog window after 300 ms (by calling CardPrinter.this.setVisible(false);).
      ActionListener task = new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
              CardPrinter.this.setVisible(false);
          }
      };
      Timer closeWnd = new Timer(300, task);
      closeWnd.start();
      //######
  }


  //use this to create an instance of this class.
  public static CardPrinter createDialog(Window owner, String vorname,
                String nachname, String id, String chipid, String gueltig, String bild  /*, DataReceiver drv*/) throws IOException {
      return new CardPrinter(owner, vorname, nachname, id, chipid, gueltig, bild  /*, drv*/);
  }


  protected void addIDCard() throws IOException {
      int idcard_move_vert=15, idcard_move_hor=76;
      tx = new JTextField(this.chipid, 8);
      jp.add(tx);
      tx.setBounds(idcard_move_hor+130, idcard_move_vert+6, 70, 20);
      Border border = BorderFactory.createLineBorder(Color.RED);
      tx.setBorder(border);
      tx.requestFocus();

      lblCounter = new JLabel("");
      lblCounter.setBounds(idcard_move_hor+270, idcard_move_vert-6, 40, 30);
      jp.add(lblCounter);
      lblCounter.requestFocus();

      System.out.println("\naddIDCard() ...");

      BufferedImage picture = IDCardLayout.loadPicture(this.bild);
      idcard = new IDCardLayout(/*this.vorname, this.nachname, this.id,*/ picture, this.bild  /*, this.gueltig*/);

      idcard.setLayout(null);
      //idcard.setBounds(idcard_move_hor, idcard_move_vert, idcard.getPreferredSize().width, idcard.getPreferredSize().height);
      idcard.setBounds(idcard_move_hor, idcard_move_vert, 50, 60);
      idcard.setBorder( new LineBorder(Color.BLACK) );
      jp.add(idcard);

      //repaint();
  }
}
package test;
/*IDCardLayout.java*/

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;

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

import org.monte.cmykdemo.CMYKJPEGImage;


public class IDCardLayout extends JPanel {
    private BufferedImage bild;
    private String bildfile;


    public IDCardLayout(BufferedImage photo, String bildfile) {
        this.bild = photo;
        this.bildfile = bildfile;
    }


    /**
     * Render graphics to the screen.
     */
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        System.out.println("\npaintComponent() ...");
        prepareGraphics(g2d);
    }


    public static BufferedImage loadPicture(String fullpath) throws IOException {
        //BufferedImage img = (BufferedImage) CMYKJPEGImage.loadImage( f.getAbsolutePath() );
        BufferedImage img = (BufferedImage) ImageIO.read( new File(fullpath) );

        return img;
    }


    //changing the rendering hints has no effect on Outofmemory-exception.
    protected void setRenderingHints(Graphics2D g2, boolean normalText) {
        if(true) {
            g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
            g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
            g2.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
        }
    }


    /**
     * Renders graphics to the screen.
     */
    protected void prepareGraphics(Graphics2D g2) {
        setRenderingHints(g2, true);

        double newHeight = 60;
        double scwidth = ( ((double)newHeight / (double)this.bild.getHeight()) ) * (double)this.bild.getWidth();
        System.out.println("\nprepareGraphics() ..." + this.bildfile);
        g2.drawImage(this.bild,  5,  5,
                    (int)scwidth,
                    (int)newHeight,
                    null, null);
    }
}

1 个答案:

答案 0 :(得分:0)

问题解决了。我不再使用OverlayLayout类了。布局看起来很不一样,但现在可以了。