Java 小程序 : free up Graphics resources

标签 java graphics applet

我的程序显示图片库,不幸的是它一次加载所有内容。我正在寻找建议来实现一种方法来加载图像并在用户单击下一步按钮后释放先前加载的图像。

更新版本,其中我更改为 JApplet 并更改了调用 paint 方法的方式。但是它仍然没有解决内存使用问题。任何帮助将不胜感激!

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JApplet;

public class JAppletGallery extends JApplet implements ActionListener {
    private Button first;
    private Button previous;
    private Button next;
    private Button last;

    static int total = 400; // initial total total images
    int imageIndex = 0; // current image

    // gets folder's location
    String folderName = "/Users/Martynas/Pictures/leicester/";
    File folder = new File(folderName);

    // initialise image object up to its total
    Image Pictures[] = new Image[total];
    static String[] imageName = new String[total];

    // constructor
    public JAppletGallery() {

    }

    public void init() {
        makeGui();
        prepareImages();
    }

    private void makeGui() {
        setBackground(Color.DARK_GRAY);
        setForeground(Color.WHITE);
        setLayout(new BorderLayout());
        setSize(800, 600);

        // init buttons
        first = new Button("First");
        first.setForeground(Color.BLACK);
        previous = new Button("Previous");
        previous.setForeground(Color.BLACK);
        next = new Button("Next");
        next.setForeground(Color.BLACK);
        last = new Button("Last");
        last.setForeground(Color.BLACK);

        // init panel holder
        Panel btnPanel = new Panel();

        btnPanel.add(first);
        btnPanel.add(previous);
        btnPanel.add(next);
        btnPanel.add(last);

        add(BorderLayout.NORTH, btnPanel);

        first.addActionListener(this);
        previous.addActionListener(this);
        next.addActionListener(this);
        last.addActionListener(this);
    }

    public void drawNext() {

        imageIndex = imageIndex + 1;
        // checks for current image
        if (imageIndex == total) {
            imageIndex = 0;
        }
        // sends index to display image
        repaint();
    }

    public void drawPrevious() {
        imageIndex = imageIndex - 1;

        if (imageIndex < 0) {
            imageIndex = total - 1;
        }
        repaint();

    }

    public void drawFirst() {
        imageIndex = 0;
        repaint();
    }

    public void drawLast() {
        imageIndex = total - 1;
        repaint();
    }


    // Manage button actions
    public void actionPerformed(ActionEvent e) {

        if (e.getSource() == previous) {
            drawPrevious();
        } else if (e.getSource() == next) {
            drawNext();
        } else if (e.getSource() == first) {
            drawFirst();
        } else if (e.getSource() == last) {
            drawLast();
        }
    }

    // gets files from a folder - sub-method of displayImage()
    public static void filesFolder(File folder) {
        File[] listOfFiles = folder.listFiles();
        int index = 0;

        // puts image names in separate index of array
        for (File file : listOfFiles) {
            if (file.isFile()) {
                // System.out.println(file.getName());
                // assigning to String array for further manipulation
                imageName[index] = file.getName();
                index++;
            }
        }
        // total images count correction
        total = index;
    }

    private void prepareImages() {
        // gets image names from the folder
        filesFolder(folder);

        for (int p = 0; p < total; p++) {

            Pictures[p] = getImage(getDocumentBase(), folderName + imageName[p]);
        }       
    }

    public void paint(Graphics g) {
        g.drawImage(Pictures[imageIndex], 0, 0, this);
    }

}

最佳答案

删除实例变量

//初始化图像对象到它的总数 Image Pictures[] = new Image[total];

或者至少在 next 和 previous 上 - 删除距离当前 n 个位置以上的元素。您现在正在缓存所有图像。

而是使一些 Pictures 变量的索引为空。在绘画中检查它是否为 null - 如果它是单独加载该插槽的图像。

同时考虑阅读命名约定和驼峰命名法——命名实例变量是小写的,所以图片而不是图片。您已经为其他变量完成了此操作,所以这里可能只是拼写错误 :-)

并且不要将 java awt 组件与 swing 混合使用。可以用

java.awt.BorderLayout; java.awt.颜色; java.awt.图形; java.awt.图像;等等

但不是像 Panel、Button 这样的组件使用 JButton ...

当您尝试释放时需要更多内存...直到垃圾回收发生。我猜如果你有超过 20 张图像是个好主意,所以缓存大小可以是 10。

示例代码 - 制作成应用程序可以再次制作成 Japplet - getdocument base 等

import java.net.URL;
import java.awt.BorderLayout;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.imageio.*;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JApplet;
import javax.swing.JComponent;

public class JAppletGallery extends JApplet implements ActionListener {
    private JButton first;
    private JButton previous;
    private JButton next;
    private JButton last;
    private int cacheSize = 2;
    static int total = 400; // initial total total images
    int imageIndex = 0; // current image
    String msg = "";

    // gets folder's location
    String folderName = "/Users/Martynas/pictures/leicester/";
    File folder = new File(folderName);

    // initialise image object up to its total
    Image pictures[] = new Image[total];
    static String[] imageName = new String[total];

    public static void main(String[] args){
        final JAppletGallery ap = new JAppletGallery();
        if(args.length > 0){
            ap.folderName = args[0];

        }
        ap.folder = new File(ap.folderName);

        final JFrame f = new JFrame("Gal ");

        javax.swing.SwingUtilities.invokeLater(new Runnable(){
            public void run(){
            //f.setDefaultCloseAction
                f.getContentPane().setLayout(null);
                f.getContentPane().add(ap);
                f.setBounds(0, 0, 700, 700);
                ap.setBounds(15, 15, 675, 675);//not a good way but fine for testing/ local
                //slp(1500)
                f.setVisible(true);

                ap.init();
                ap.start();
                f.invalidate();
                f.repaint();
            }
        });
    }

    // constructor
    public JAppletGallery() {

    }

    public void init() {
        makeGui();
        prepareImages();
    }

    private void makeGui() {
        setBackground(Color.DARK_GRAY);
        setForeground(Color.WHITE);
        setLayout(new BorderLayout());
        setSize(800, 600);

        // init buttons
        first = new JButton("First");
        first.setForeground(Color.BLACK);
        previous = new JButton("Previous");
        previous.setForeground(Color.BLACK);
        next = new JButton("Next");
        next.setForeground(Color.BLACK);
        last = new JButton("Last");
        last.setForeground(Color.BLACK);

        // init panel holder
        JPanel btnPanel = new JPanel();
        btnPanel.setLayout(new java.awt.FlowLayout());
        btnPanel.add(first);
        btnPanel.add(previous);
        btnPanel.add(next);
        btnPanel.add(last);

        add(BorderLayout.NORTH, btnPanel);
        ImgShow imgs = new ImgShow();
        imgs.parent = this;
        add(BorderLayout.CENTER, imgs);

        first.addActionListener(this);
        previous.addActionListener(this);
        next.addActionListener(this);
        last.addActionListener(this);
    }

    public void drawNext() {

        imageIndex = imageIndex + 1;
        // checks for current image
        if (imageIndex == total) {
            imageIndex = 0;
        }
        picsLoadAndTrim();
        // sends index to display image
        repaint();
    }

    public void drawPrevious() {
        imageIndex = imageIndex - 1;

        if (imageIndex < 0) {
            imageIndex = total - 1;
        }
        picsLoadAndTrim();
        repaint();

    }

    private void picsLoadAndTrim() {

        int before = imageIndex - cacheSize;
        int before2 = total;
        if(before < 0){
            before2 = total + before;
        }
        int after = imageIndex + cacheSize;
        int after2 = -1;
        if(after >= total){
            after2 = after - total;
        }
        System.out.println("total " + total + " imageIndex " + imageIndex  + ", before " + before + ", after " + after + ", before2 " + before2+ ", after2 " + after2);
        for(int i =0; i < total ; i++){
            if((i >= before && i <= after) ||  (i <= after2) || (i >= before2)){
                System.out.println("CHECK " + i);
                if(pictures[i] ==null){//load only if not currently loaded

                    try {
                        pictures[i] = ImageIO.read(new File(folder, imageName[i]));
                    //loadImage(getDocumentBase()  , imageName[i]);
                    } catch (Exception e) {
                        msg = msg + " " + imageName[i];
                    }
                }else{
                }
            }else{
                System.out.println("rel " + i);
                pictures[i] = null; //release if loaded before
            }
        }
    }

    public URL getDocumentBase(){
        URL u = null;//super.getDocumentBase();
        try{
            if(u==null)u = new URL("file://" + folderName);
        }catch(Exception e){
            System.out.println(e);
        }
        return u;
    }
    public void drawFirst() {
        imageIndex = 0;
        picsLoadAndTrim();
        repaint();

    }

    public void drawLast() {
        imageIndex = total - 1;
        picsLoadAndTrim();
        repaint();
    }


    // Manage button actions
    public void actionPerformed(ActionEvent e) {

        if (e.getSource() == previous) {
            drawPrevious();
        } else if (e.getSource() == next) {
            drawNext();
        } else if (e.getSource() == first) {
            drawFirst();
        } else if (e.getSource() == last) {
            drawLast();
        }
    }

    // gets files from a folder - sub-method of displayImage()
    public  void filesFolder(File folder) {
        File[] listOfFiles = folder.listFiles();
        int index = 0;

        // puts image names in separate index of array
        for (File file : listOfFiles) {
            String s = file.getName().toLowerCase();
            if (file.isFile() && (s.endsWith(".png") || s.endsWith("jpg"))) {
                // System.out.println(file.getName());
                // assigning to String array for further manipulation
                imageName[index] = file.getName();
                index++;
            }
        }
        // total images count correction
        total = index;
        if(cacheSize > total)cacheSize = total;
    }

    private void prepareImages() {
        // gets image names from the folder
        filesFolder(folder);
        picsLoadAndTrim();
        //for (int p = 0; p < 1; p++) {

          //  pictures[p] = getImage(getDocumentBase(), folderName + imageName[p]);
        //}
    }



}

class ImgShow extends JComponent{
    JAppletGallery parent;


    public void paint(Graphics g) {
            if(parent.pictures[parent.imageIndex] != null){
                g.drawImage(parent.pictures[parent.imageIndex], 0, 35, this);
            }else{
                g.drawString(parent.msg, 10, 35);
                //err
            }
    }
}

此代码可以被强制执行,但它显示你释放/使 null。

关于Java 小程序 : free up Graphics resources,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24542272/

相关文章:

c++ - OpenGL:QApplication的执行流程

java - 我可以在 Java Applet 中使用 JNI 吗?

java - 用随机颜色更新小程序

JAVA数组与对象错误问题(初学者)

java - 使用不同类的矩阵乘法 - Java

java - 比较不同 JButton 的文本

c++ - 带阴影的聚光灯变成方形

java - 不支持的 JNI 版本 0xFFFFFFFF

java - HttpUrlConnection 代理身份验证进入重定向循环

java - 多态性有何重要意义?