Results 1 to 8 of 8
  1. #1
    lmtoe is offline Member
    Join Date
    Jan 2011
    Posts
    4
    Rep Power
    0

    Default calling Graphics functions within for loop yields strange results

    I have a program that works fine (paints graphics where I expect and graphics don't disappear on window resize/minimize) if I call Graphics functions individually, However if I make the same calls within a for loop, the graphics are shifted and also disappear on window re-size or minimize.

    Specifically, I have an array (grades[]), and making the following calls within my paintComponent(Graphics g) method...

    Java Code:
    g.drawRect(50, 400-grades[0]*scale, 35, grades[0]*scale);
    g.drawRect(100, 400-grades[1]*scale, 35, grades[1]*scale);
    g.drawRect(150, 400-grades[2]*scale, 35, grades[2]*scale);
    g.drawRect(200, 400-grades[3]*scale, 35, grades[3]*scale);
    g.drawRect(250, 400-grades[4]*scale, 35, grades[4]*scale);
    The above code works great, and is fine for a very small number of instances in the array; however becomes a burden if the array is large. This is obviously the perfect place to use a for loop; so I changed the code to this (still from within the paintGraphics method...

    Java Code:
    width = 35;
    offset = 50;
    for (int z=0; z<grades.length; z++) {
                
                y = 400 - grades[z]*scale;
                height = grades[z]*scale;
                g.drawRect(x, y, width, height);
                x+=offset;
    }
    Best I can tell, this should be no different then the above code.

    Any thoughts on what might be wrong here? I wouldn't think that calling graph functions would cause a problem. For reference, I am pasting the entire program...

    GradeHistogram.java is the viewer with main() which uses
    HistogramComponent.java

    Java Code:
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.Scanner;
    
    import javax.swing.JFrame;
    
    public class GradeHistogram {
    
        /**
         * the main() Method
         * @param args
         */
        public static void main(String[] args) {
            
            int count = 0;
            int gradeCountA = 0;
            int gradeCountB = 0;
            int gradeCountC = 0;
            int gradeCountD = 0;
            int gradeCountF = 0;
            
            int grade;
            String fileName;
            Scanner input = new Scanner(System.in);
            Scanner infile = null;
            
            // Greeting and get the file for input
            // Note: do to sizing limitation the current histogram can only hold up to 400 count of a single letter
            System.out.println("This program reads integers from a file that represent " +
            		"exam grades; and will print out a histogram of the Letter grades\n");
            
            System.out.println("Please enter the text file: ");
            fileName = input.next();
            
            // try to open file
            try {
                 infile = new Scanner(new File(fileName));
            } catch(FileNotFoundException e) {
                System.out.printf("Unable to open input file %s\n", fileName);
                System.exit(1);        
              }
            
            // Read data from file and count each letter grade (standard 10 pt. scale)
            while (infile.hasNextInt()) {
                grade = infile.nextInt();
                if (grade >= 90) {
                    gradeCountA++;
                }
                else if (grade >= 80) {
                    gradeCountB++;
                }
                else if (grade >= 70) {
                    gradeCountC++;
                }
                else if (grade >= 60) {
                    gradeCountD++;
                }
                else {
                    gradeCountF++; //You fail
                }
                count++;
            }
            
            // print the output of the grade counts
            System.out.println("A: " + gradeCountA);
            System.out.println("B: " + gradeCountB);
            System.out.println("C: " + gradeCountC);
            System.out.println("D: " + gradeCountD);
            System.out.println("F: " + gradeCountF);
            
            // Create the frame for holding the histogram
            JFrame frame = new JFrame("Histogram of Letter Grade Distrobution from " + fileName);
            frame.setSize(600, 600);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            // Put grade counts into array to pass to HistogramComponent
            int [] grades = {gradeCountA, gradeCountB, gradeCountC, gradeCountD, gradeCountF};
            
            //set bar graph scale to increase size of the bars if relatively small number count
            int scale = 1;
            if (count <= 10) {
                scale = 25;
            }
            else if (count <= 20) {
                scale = 20;
            }
            else if (count <= 30) {
                scale = 15;
            }
            else if (count <= 40) {
                scale = 10;
            }
            else if (count <= 50) {
                scale = 5;
            }
            else {
                scale = 1;
            }
            
            // Create HistogramConponent; add to frame & set frame visible
            HistogramComponent component = new HistogramComponent(grades,scale);
            frame.add(component);
            frame.setVisible(true);
    
    
        }
    
    }
    Java Code:
    import java.awt.Graphics;
    
    import javax.swing.JComponent;
    
    public class HistogramComponent extends JComponent {
        private int x,y,width,height, offset;
        private int scale;
        private int[] grades;
        private String letA = "A";
        private String letB = "B";
        private String letC = "C";
        private String letD = "D";
        private String letF = "F";
        
        /**
         * Constructs a HistogramComponent object
         * @param varGrades array of ints representing number of each grade
         * @param varScale sets the scale multiplier to increase the size of the bar graphs
         */
        public HistogramComponent (int[] varGrades, int varScale) {
            
            grades = varGrades;
            scale = varScale;
            x = 50;
            y = 0;
            width = 35;
            height = 0;
            offset = 50;
        }
        
        /**
         * The graphics component
         */
        public void paintComponent (Graphics g) {
            
            // draw base line
            g.drawLine(50, 400, 250, 400);
            for (int z=0; z<grades.length; z++) {
                // skipping the drawString calls... First trying to get the rects to work properly
                y = 400 - grades[z]*scale;
                height = grades[z]*scale;
                g.drawRect(x, y, width, height);
                x+=offset;
            }
     
            /* The following works but want to use a for loop
            // draw Grade A Bar Graph
            g.drawString ("" + grades[0], 60, 400-grades[0]*scale - 15);
            g.drawString(letA, 60, 425);
            g.drawRect(50, 400-grades[0]*scale, 35, grades[0]*scale);
            
            // draw Grade B Bar Graph
            g.drawString ("" + grades[1], 110, 400-grades[1]*scale - 15);
            g.drawString(letB, 110, 425);
            g.drawRect(100, 400-grades[1]*scale, 35, grades[1]*scale);
            
            // draw Grade C Bar Grapgh
            g.drawString ("" + grades[2], 160, 400-grades[2]*scale - 15);
            g.drawString(letC, 160, 425);
            g.drawRect(150, 400-grades[2]*scale, 35, grades[2]*scale);
            
            // draw Grade D Bar Grapgh
            g.drawString ("" + grades[3], 210, 400-grades[3]*scale - 15);
            g.drawString(letD, 210, 425);
            g.drawRect(200, 400-grades[3]*scale, 35, grades[3]*scale);
            
            // draw Grade F Bar Graph
            g.drawString ("" + grades[4], 260, 400-grades[4]*scale - 15);
            g.drawString(letF, 260, 425);
            g.drawRect(250, 400-grades[4]*scale, 35, grades[4]*scale);
            */
            
        } // End paintComponent
        
       
    
    } // end Class

  2. #2
    doWhile is offline Moderator
    Join Date
    Jul 2010
    Location
    California
    Posts
    1,641
    Rep Power
    7

    Default

    a) You should make a call to super.paintComponent(g) in your paintComponent method
    b) The x variable will be perpetually incremented, causing the drawing to go further and further to the right. For demo purposes, initialize x to a value at the start of the paintComponent method and see what happens....

  3. #3
    lmtoe is offline Member
    Join Date
    Jan 2011
    Posts
    4
    Rep Power
    0

    Default

    for b) on the x value, yes, I agree -- there are many aspects of this that "need improvement" and that is certaonly one of them.

    However for a) Where exactly would I put the super.paintComponent(g). I tried adding at various places. Here is code showing where I added it and had tried running in each place individually as well as together, but the issue still exists where the whole paint is shifted and disappears on resize...

    Java Code:
        public void paintComponent (Graphics g) {
            //super.paintComponent(g);
            
            // draw base line
            g.drawLine(50, 400, 250, 400);
            for (int z=0; z<grades.length; z++) {
                
                y = 400 - grades[z]*scale;
                height = grades[z]*scale;
                g.drawRect(x, y, width, height);
                x+=offset;
                //super.paintComponent(g);
            }
            super.paintComponent(g);

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by lmtoe View Post
    for b) on the x value, yes, I agree -- there are many aspects of this that "need improvement" and that is certaonly one of them.
    No, this is the cause of your problem and needs to be fixed. You need to reinitialize those variables at the start of paintComponent.


    However for a) Where exactly would I put the super.paintComponent(g). I tried adding at various places. Here is code showing where I added it and had tried running in each place individually as well as together, but the issue still exists where the whole paint is shifted and disappears on resize...

    Java Code:
        public void paintComponent (Graphics g) {
            //super.paintComponent(g);
            
            // draw base line
            g.drawLine(50, 400, 250, 400);
            for (int z=0; z<grades.length; z++) {
                
                y = 400 - grades[z]*scale;
                height = grades[z]*scale;
                g.drawRect(x, y, width, height);
                x+=offset;
                //super.paintComponent(g);
            }
            super.paintComponent(g);
    super call should be at the start of the method > 90% of the time.

  5. #5
    lmtoe is offline Member
    Join Date
    Jan 2011
    Posts
    4
    Rep Power
    0

    Default

    Reinitializing those variables at the start of paintComponent did the trick. Thank you very much!

    Apologies up front for the newb question (just trying to understand the reasoning here), but WHY do I have to reinitialize them? I am declaring them as global variables of the class, and when not reinitialized within paintComponent those variables appear to be read in (it's just there is an offset and the graphic disappears on resize).

  6. #6
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    It's much better for you to see for yourself by steping through your program and thinking through the logic of what happens as you do this, and you'll see why.

  7. #7
    lmtoe is offline Member
    Join Date
    Jan 2011
    Posts
    4
    Rep Power
    0

    Default

    ahh I think I get it... the paintGraphics is actually called with each resize/minimize, so by not declaring it within paintGraphics, it keeps increasing indefinitely with each resize and effectively moves the graph off the screen as it increases beyond the screen size.

    So by reinitializing within the paintGraphics, the x variable gets reset to the original position (150) on each resize/minimize.

    Thanks a lot for your help. Again I really appreciate it

  8. #8
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,452
    Rep Power
    20

    Default

    Quote Originally Posted by doWhile View Post
    a) You should make a call to super.paintComponent(g) in your paintComponent method
    JComponent doesn't have a UI delegate, so super.paintComponent(...) does nothing.

    db

Similar Threads

  1. Explanation of Nested Loop (very strange)
    By Jonotron in forum New To Java
    Replies: 5
    Last Post: 01-09-2011, 03:54 AM
  2. Calling java functions from c++
    By khajalid in forum New To Java
    Replies: 13
    Last Post: 10-12-2010, 11:50 PM
  3. Replies: 0
    Last Post: 03-04-2009, 10:51 AM
  4. Replies: 13
    Last Post: 07-06-2008, 10:11 AM
  5. showing results in a for loop randomly
    By vexity in forum New To Java
    Replies: 4
    Last Post: 04-29-2008, 05:24 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •