Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ. (επεξεργασμένο)

Για κάποιο λόγο το παρακάτω πρόγραμμα (ένα καρουσελ φωτογραφιών) πιάνει πάρα πολύ χώρο στην ραμ. Να πω πως μόνο όταν αλλάζω φωτογραφίες (με τα δεξιά και αριστερά κουμπιά) ανεβαίνει η χρήση της ραμ και μετά δεν κατεβαίνει ποτέ. Ο μόνος λόγος που μπορώ να σκεφτώ γιατί συμβαίνει αυτό είναι επειδή υπάρχουν references τα οποία συνεχίζουν τα δείχνουν διάφορα objects. Βέβαια υπάρχει και η περίπτωση να μην χρησιμοποιώ σωστά διάφορες μεθόδους, δεν ξέρω. Τι λέτε εσείς;

Spoiler
package erg10b;

import java.io.File;
import javax.swing.ImageIcon;

public class Pictures extends javax.swing.JFrame {

    public Pictures() {
        initComponents();
        loadImages();
    }

    private void loadImages() {
        String userDir = System.getProperty("user.dir").replace('\\', '/');
        File imgDir = new File(userDir + "/src/erg10b/images");
        String[] files = imgDir.list();

        int i = 0;
        for (; i < files.length && files[i] != null; i++) {
            IMAGE_PATHS[i] = userDir + "/src/erg10b/images/" + files[i];
        }
        picMaxIndex = i - 1;
        
        mainPicture.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[0]).getImage().getScaledInstance(500, 450, java.awt.Image.SCALE_FAST)));
        leftPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[picMaxIndex]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
        midPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[0]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
        rightPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[1]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
    }

    private final int MAX_PICS = 100000;
    private final String[] IMAGE_PATHS = new String[MAX_PICS];
    private int picIndex = 0;
    private int picMaxIndex; // This is needed because IMAGE_PATHS can have less elements than MAX_PICS

   

    private void rightMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightMouseClicked
        if (picIndex == picMaxIndex - 1) {
            picIndex = -1;
        }

        mainPicture.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[++picIndex]).getImage().getScaledInstance(500, 450, java.awt.Image.SCALE_FAST)));

        leftPic.setIcon(midPic.getIcon());
        midPic.setIcon(rightPic.getIcon());

        if (picIndex == picMaxIndex - 1) {
            rightPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[0]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
        } else {
            rightPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[picIndex + 1]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
        }
    }//GEN-LAST:event_rightMouseClicked

    private void leftMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftMouseClicked
        if (picIndex == 0) {
            picIndex = picMaxIndex;
        }

        mainPicture.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[--picIndex]).getImage().getScaledInstance(500, 450, java.awt.Image.SCALE_FAST)));

        rightPic.setIcon(midPic.getIcon());
        midPic.setIcon(leftPic.getIcon());

        if (picIndex == 0) {
            leftPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[picMaxIndex - 1]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
        } else {
            leftPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[picIndex - 1]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
        }
    }//GEN-LAST:event_leftMouseClicked

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Pictures().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel left;
    private javax.swing.JLabel leftPic;
    private javax.swing.JLabel mainPicture;
    private javax.swing.JLabel midPic;
    private javax.swing.JLabel right;
    private javax.swing.JLabel rightPic;
    // End of variables declaration//GEN-END:variables
}

 

 

Αν θέλετε να το τρέξετε και εσείς (είναι netbeans project): Erg10b.zip

Στο src/erg10b/images βαλτε εικονες (30 καλά είναι) και δοκιμάστε το.

 

Update: Ξέχασα να πω πως οι leftMouseClicked και rightMouseClicked φαίνεται να έχουν πρόβλημα, άρα μην κοιτάτε τις άλλες μεθόδους (εκτός αν έχουν κάτι τρομερά λάθος που αδυνατώ να καταλάβω :P).

Επεξ/σία από xristos97
Δημοσ.

Οι φωτογραφίες που έχω βάλει εγώ είναι 44 μεγα και η ραμ φτάνει στα ~700 μεγα. Το θέμα είναι ότι τις φωτογραφίες τις φτιάχνω κάθε φορά που χρειάζονται χωρίς να τις αποθηκεύω κάπου.

Δημοσ. (επεξεργασμένο)

Sorry αλλά δε κρατήθηκα 😇

    private void rightMouseClicked(java.awt.event.MouseEvent evt) 
	{//GEN-FIRST:event_rightMouseClicked
		SetIcons(-1, -1, 0, picIndex + 1);
    }//GEN-LAST:event_rightMouseClicked

    private void leftMouseClicked(java.awt.event.MouseEvent evt) 
	{//GEN-FIRST:event_leftMouseClicked
        SetIcons(0,picIndex, picMaxIndex - 1, picIndex - 1);
    }//GEN-LAST:event_leftMouseClicked
	
	private void SetIcons(int a, int b, int c, int d)
	{
		if (picIndex == a) 
            picIndex = b;
        
        mainPicture.setIcon(new ImageIcon(new 	   ImageIcon(IMAGE_PATHS[--picIndex]).getImage().getScaledInstance(500, 450, java.awt.Image.SCALE_FAST)));

        rightPic.setIcon(midPic.getIcon());
        midPic.setIcon(leftPic.getIcon());

        if (picIndex == a) 
            leftPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[c]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
        else 
		    leftPic.setIcon(new ImageIcon(new ImageIcon(IMAGE_PATHS[d]).getImage().getScaledInstance(100, 75, java.awt.Image.SCALE_FAST)));
	}

υ.γ. αν αλλάξεις φωτογραφία και πας από την Α στη Β, και μετά πάλι στην Α, ανεβαίνει η μνήμη και στο βήμα απ' τη Β στην Α ;

Επεξ/σία από Alithinos
Δημοσ.

Όχι δεν ανεβαίνει. Άλλωστε άμα τις περάσω όλες τις φωτογραφίες μετά σταματάει να ανεβαίνει, άρα κάπου μένουν στην μνήμη.

 

Η SetIcons που έφτιαξες πετάει ArrayIndexOutOfBounds. Επίσης είναι προφανές ότι το rightPic.setIcon(midPic.getIcon()); δεν θες να είναι το μόνο που θα τρέχει, θες και το leftPic.setIcon(midPic.getIcon());. Αν τρέξεις το πρόγραμμα θα καταλάβεις γιατί.

Δημοσ.

Η getScaledInstance επιστρέφει ένα Image και επειδή δεν υπάρχει άμεσος τρόπος να ένα πάρω ImageIcon ξανά καλώ τον constructor της ImageIcon με ένα Image ως arguement (αυτό που επιστρέφει η getScaledInstance).

Δημοσ.

τι σημαίνει "δεν υπάρχει ..άμεσος τρόπος";

Βάζεις σε μια μεταβλητή  τύπου image την εικόνα σου! Αυτός είναι ο τρόπος!

Δες το δεύτερο παράδειγμα εδώ: http://zetcode.com/java/imageicon/

        ImageIcon originalIcon = new ImageIcon("slovakia.png");
        JLabel originalLabel = new JLabel(originalIcon);

        int width = originalIcon.getIconWidth() / 2;
        int height = originalIcon.getIconHeight() / 2;

        Image scaled = scaleImage(originalIcon.getImage(), width, height);

 

Δημοσ. (επεξεργασμένο)

Μου φαίνεται πως το έκανα (όχι με αυτό που μου έδειξες solarpower, θα το δω βέβαια και αυτό)

 

Η αλλαγή των right και left MouseClicked (η μόνη διαφορά είναι η κλήση των μεθόδων που έβαλα):

Spoiler
private void rightMouseClicked(java.awt.event.MouseEvent evt) {                                   
        if (picIndex == picMaxIndex - 1) {
            picIndex = -1;
        }

        mainPicture.setIcon(createScaledImageIcon(IMAGE_PATHS[++picIndex], 500, 450));

        leftPic.setIcon(midPic.getIcon());
        midPic.setIcon(rightPic.getIcon());

        if (picIndex == picMaxIndex - 1) {
            rightPic.setIcon(createScaledImageIcon(IMAGE_PATHS[0], 100, 75));
        } else {
            rightPic.setIcon(createScaledImageIcon(IMAGE_PATHS[picIndex + 1], 100, 75));
        }
    }                                  

    private void leftMouseClicked(java.awt.event.MouseEvent evt) {                                  
        if (picIndex == 0) {
            picIndex = picMaxIndex;
        }

        mainPicture.setIcon(createScaledImageIcon(IMAGE_PATHS[--picIndex], 500, 450));

        rightPic.setIcon(midPic.getIcon());
        midPic.setIcon(leftPic.getIcon());

        if (picIndex == 0) {
            leftPic.setIcon(createScaledImageIcon(IMAGE_PATHS[picMaxIndex - 1], 500, 450));
        } else {
            leftPic.setIcon(createScaledImageIcon(IMAGE_PATHS[picIndex - 1], 500, 450));
        }
    }        

 

 

Η νέα μέθοδος που έφτιαξα:

Spoiler
private ImageIcon createScaledImageIcon(String path, int width, int height) {
        try {
            BufferedImage bi = ImageIO.read(new File(path));
            
            return new ImageIcon(bi.getScaledInstance(width, height, java.awt.Image.SCALE_FAST));
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return null;
    }

 

 

Η μνήμη κατέβηκε στα 200 μεγα απο τα 800 μεγα. Βέβαια καταλαβαίνεις λίγο lag καθώς φορτώνουν άλλες εικόνες. Ίσως να φταίει το ImageIO.read. 

Επεξ/σία από xristos97
Δημοσ. (επεξεργασμένο)
2 ώρες πριν, xristos97 είπε

Όχι δεν ανεβαίνει. Άλλωστε άμα τις περάσω όλες τις φωτογραφίες μετά σταματάει να ανεβαίνει, άρα κάπου μένουν στην μνήμη.

Η SetIcons που έφτιαξες πετάει ArrayIndexOutOfBounds. Επίσης είναι προφανές ότι το rightPic.setIcon(midPic.getIcon()); δεν θες να είναι το μόνο που θα τρέχει, θες και το leftPic.setIcon(midPic.getIcon());. Αν τρέξεις το πρόγραμμα θα καταλάβεις γιατί.

Ναι η αλήθεια είναι δε το δοκίμασα. Έκανα τις αλλαγές στα γρήγορα στη φόρμα, και ίσως κάπου έχει μια απροσεξία που δε μου την είπε κάποιος comipler.  Απλά έχω συνηθίσει σε αυτό που δουλεύω κάτι μήνες να κάνω συνέχεια έλεγχο τα scripts αν επαναλαμβάνω πράγματα, και να τα συμμαζεύω ώστε να μειώνω το συνολικό αριθμό γραμμών, και να είναι πιο εύκολος ο κώδικας στις αλλαγές.

Επί του θέματος: Δε το έτρεξα το πρόγραμμα επειδή δουλεύω με C# που συντακτικά είναι σχεδόν ολόιδια με τη Java και έτσι κάποιος που ξέρει τη μια γλώσσα μπορεί να διαβάσει άνετα κώδικα της άλλης. Αλλά δεν έχω IDE της Java για να κάνω compile και να το δοκιμάσω. Μήπως υπάρχει περίπτωση να φταιν τα πολλά new ; Δοκίμασε να έχεις έναν αριθμό imageIcons ως πεδία της κλάσης, και όταν χρειάζεται να αλλάξει το ποιες φωτογραφίες θα εμφανίζονται απλά να ορίζεις την αξία των πεδίων με τη νέα τιμή.

edit: Οκ αφού βρήκες λύση και μείωσες τη μνήμη έχει καλώς. Ίσως να έφταιγαν τα πολλά new. Να δημιουργούσαν δηλαδή duplicate αντικείμενα τα οποία όμως να μην αφαιρούνταν από τη μνήμη με το τέλος της μεθόδου.

Επεξ/σία από Alithinos
Δημοσ. (επεξεργασμένο)

Η imageIcon έχει έναν MediaTracker και αυτός αποθηκεύει τα icons ώστε να μην τα ξανά φτιάχνει (κάτι τέτοιο, ίσως να μην το κατάλαβα καλά). Γι'αυτό μάλλον ανέβαινε η μνήμη και σταματούσε να ανεβαίνει όταν φόρτωναν όλες οι εικόνες.

Επεξ/σία από xristos97
Δημοσ. (επεξεργασμένο)

Είναι απαράδεκτη αυτή η κατανάλωση μνήμης!

Τi μέγεθος σε pixels είναι μια αντιπροσωπευτική φωτογραφία;

Απ΄ότι είδα παραπάνω τις θες μικρές 500χ450 pixels  - αυτό είναι το πλαίσιο που θες να φανεί, αλλά μήπως χαλάς την αναλογία πλευρών της αυθεντικής φωτογραφίας;

δες λίγο και αυτό:

https://github.com/keshrath/ImageLoader/blob/master/src/at/mukprojects/imageloader/image/ImageList.java

βάζεις τις φωτογραφίες σε μια λίστα και τις ζητάς στα events από εκεί. Δεν φορτώνει δεύτερη φορά.

Επεξ/σία από solarpower

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...