CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Mar 2009
    Posts
    22

    JComponent Doesn't Add To JFrame

    I'm making some kind of a rookie mistake here, and I've stared at it long enough that I think I need a fresh set of eyes to tell me where my error is. I'm creating a a program to simulate a fishtank with three fish objects that extend the Thread class and displays graphically. My problem is that my component does not display in my frame, and I'm not sure why. Here's my code:

    Fish Class:
    Code:
    package fishthreads;
    
    import java.awt.Color;
    import java.awt.Polygon;
    
    /**
     *
     */
    public class Fish extends Thread
    {
        private int[] x, y;
        private Color color;
        private int sleepTime, cornerPoints, xBound, yBound, xSteps, ySteps;
        private Polygon fishShape;
        private boolean swim;
    
        /**
         * Construct a default fish object with the values set to null
         */
        public Fish()
        {
            super();
            this.x = null;
            this.y = null;
            this.color = null;
            this.sleepTime = 0;
            this.cornerPoints = 0;
            this.xBound = 0;
            this.yBound = 0;
            this.fishShape = null;
            this.swim = true;
            this.xSteps = this.ySteps = 1;
        }
    
        /**
         * Construct a fish object with the supplied parameters
         * @param x the x-coordinates
         * @param y the y-coordinates
         * @param c the color of the fish
         * @param s the time for the fish to sleep between thread movements
         * @param cp the number of corner points
         * @param xb the upper boundary of the aquarium on the x-plane
         * @param yb the upper boundary of the aquarium on the y-plane
         * @param xs the x-coordinate stepping (or swimming) translation value
         * @param ys the x-coordinate stepping (or swimming) translation value
         */
        public Fish(int[] x, int[] y, Color c, int s, int cp, int xb, int yb, int xs, int ys)
        {
            super();
            this.x = x;
            this.y = y;
            this.color = c;
            this.sleepTime = s;
            this.cornerPoints = cp;
            this.xBound = xb;
            this.yBound = yb;
            this.swim = true;
            this.xSteps = xs;
            this.ySteps = ys;
            this.fishShape = new Polygon(x, y, cp);
        }
    
        /**
         * Gets the Fish object's color
         * @return the color
         */
        public Color getColor() {return this.color;}
    
        /**
         * Gets the Fish object's number of corner points
         * @return the number of corner points
         */
        public int getCornerPoints() {return this.cornerPoints;}
    
        /**
         * Get's the Fish object's polygon
         * @return the Fish object's polygon
         */
        public Polygon getFishShape() {return this.fishShape;}
    
        /**
         * Gets the Fish object's sleep time between executions of the thread
         * @return the sleep time between executions of the thread
         */
        public int getSleepTime() {return this.sleepTime;}
    
        /**
         * Gets the Fish object's swimming truth value
         * @return the truth of the swim value designated to be true if supposed to 
         * swim, false otherwise
         */
        public boolean getSwim() {return this.swim;}
    
        /**
         * Gets the Fish object's x-coordinates
         * @return the x-coordinates
         */
        public int[] getX() {return this.x;}
    
        /**
         * Gets the Fish object's upper boundary of the aquarium on the x-plane
         * @return the upper boundary of the aquarium on the y-plane
         */
        public int getXBound() {return this.xBound;}
    
        /**
         * Gets the Fish object's x-coordinate stepping (or swimming) translation 
         * value
         * @return the x-coordinate stepping (or swimming) translation value
         */
        public int getXSteps() {return this.xSteps;}
    
        /**
         * Get's the Fish object's y-coordinates
         * @return
         */
        public int[] getY() {return this.y;}
    
        /**
         * Gets the Fish object's upper boundary of the aquarium on the y-plane
         * @return the upper boundary of the aquarium on the y-plane
         */
        public int getYBound() {return this.yBound;}
    
        /**
         * Gets the Fish object's y-coordinate stepping (or swimming) translation
         * value
         * @return the y-coordinate stepping (or swimming) translation value
         */
        public int getYSteps() {return this.ySteps;}
    
        /**
         * Sets the Fish object's color
         * @param c the color to set for the Fish
         */
        public void setColor(Color c) {this.color = c;}
    
        /**
         * Sets the Fish object's number of corner points
         * @param cp the number of corner points to set
         */
        public void setCornerPoints(int cp)
        {
            this.cornerPoints = cp;
            this.fishShape = new Polygon(this.x, this.y, cp);
        }
    
        /**
         * Sets the Fish object's polygon to the supplied polygon
         * @param fs the polygon to set the fish shape to
         */
        public void setFishShape(Polygon fs) {this.fishShape = fs;}
    
        /**
         * Sets the Fish object's sleep time between thread executions, in
         * milliseconds
         * @param s the sleep time between executions to set, in milliseconds
         */
        public void setSleepTime(int s) {this.sleepTime = s;}
    
        /**
         * Sets the Fish object's swimming truth value
         * @param s the truth of the swim value designated to be true if supposed to 
         * swim, false otherwise
         */
        public void setSwim(boolean s) {this.swim = s;}
    
        /**
         * Sets the Fish object's x-coordinates
         * @param x the x-coordinates to set
         */
        public void setX(int[] x)
        {
            this.x = x;
            this.fishShape = new Polygon(x, this.y, this.cornerPoints);
        }
    
        /**
         * Sets the Fish object's the upper x-boundary of the aquarium
         * @param xb the upper x-boundary of the aquarium
         */
        public void setXBound(int xb) {this.xBound = xb;}
    
        /**
         * Sets the Fish object's x-coordinate stepping (or swimming) translation 
         * value
         * @param xs the x-coordinate stepping (or swimming) translation value
         */
        public void setXSteps(int xs) {this.xSteps = xs;}
    
        /**
         * Sets the Fish object's y-coordinates
         * @param y the y-coordinates to set
         */
        public void setY(int[] y)
        {
            this.y = y;
            this.fishShape = new Polygon(this.x, y, this.cornerPoints);
        }
    
        /**
         * Sets the Fish object's the upper y-boundary of the aquarium
         * @param yb the upper y-boundary of the aquarium
         */
        public void setYBound(int yb) {this.yBound = yb;}
    
        /**
         * Sets the Fish object's y-coordinate stepping (or swimming) translation
         * value
         * @param ys the y-coordinate stepping (or swimming) translation value
         */
        public void setYSteps(int ys) {this.xSteps = ys;}
    
        /**
         * Checks if the fish has reached the x-coordinate edge of the aquarium
         * @return true if at the x-coordinate edge of the aquarium, false otherwise
         */
        public boolean checkXBound()
        {
            for(int i = 0; i < this.yBound; i++)
            {
                //right-most boundary
                if(this.fishShape.contains(this.xBound, i))
                    return true;
                //left-most boundary
                else if(this.fishShape.contains(0, i));
                    return true;
            }
            return false;
        }
    
        /**
         * Checks if the fish has reached the y-coordinate edge of the aquarium
         * @return true if at the y-coordinate edge of the aquarium, false otherwise
         */
        public boolean checkYBound()
        {
            for(int i = 0; i < this.xBound; i++)
            {
                //bottom-most boundary
                if(this.fishShape.contains(i, this.yBound))
                    return true;
                //top-most boundary
                else if(this.fishShape.contains(i, 0));
                    return true;
            }
            return false;
        }
    
        /**
         * Change the x-coordinate direction of the Fish object
         */
        public void changeXDirection()
        {
            //find max
            int max = this.x[0];
            for (int i = 1; i < this.x.length; i++)
                if (this.x[i] > max) max = this.x[i];
    
            //flip hoirizontal based on max
            for(int i = 0; i < this.x.length; i++)
                this.x[i] = max - this.x[i];
        }
    
        /**
         * Change the y-coordinate direction of the Fish object
         */
        public void changeYDirection()
        {
            //find max
            int max = this.y[0];
            for (int i = 1; i < this.y.length; i++)
                if (this.y[i] > max) max = this.y[i];
    
            //flip hoirizontal based on max
            for(int i = 0; i < this.y.length; i++)
                this.y[i] = max - this.y[i];
        }
    
        /**
         * Sets the Fish object in "motion", checking the boundary conditions and
         * adjusting as necessary when reaching boundaries
         */
        public void move()
        {
            while(this.swim == true)
            {
                fishShape.translate(xSteps, ySteps);
                if(this.checkXBound() == true)
                    this.changeXDirection();
                else if(this.checkYBound() == true)
                    this.changeYDirection();
            }
        }
    
        /**
         *
         */
        @Override
        public void run()
        {
            this.move();
            try{this.sleep(this.sleepTime);}
            //more here later
            catch (InterruptedException ex){System.out.println("Error");}
        }
    }
    FishComponent Class:
    Code:
    package fishthreads;
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.util.ArrayList;
    import javax.swing.JComponent;
    
    /**
     *
     */
    public class FishComponent extends JComponent
    {
        int[] x = {0, 18, 24, 30, 48, 60, 60, 54, 60, 48, 30, 24, 0};
        int[] y = {0, 18, 6, 0, 0, 12, 18, 24, 24, 36, 36, 30, 36};
        ArrayList<Fish> fishList;
    
        /**
         * Create a Fish Component object to display the fish in a "tank"
         */
        public FishComponent()
        {
            fishList = new ArrayList<Fish>();
            fishList.add(new Fish(x, y, Color.red, 250, 13, this.getWidth(), this.getHeight(), 3, 3));
            fishList.add(new Fish(x, y, Color.blue, 500, 13, this.getWidth(), this.getHeight(), 5, 5));
            fishList.add(new Fish(x, y, Color.green, 100, 13, this.getWidth(), this.getHeight(), 7, 7));
    
            for(int i = 0; i < fishList.size(); i++) fishList.get(i).start();
        }
    
        /**
         * Add another Fish object to the "tank"
         * @param f the Fish object to add
         */
        public void addFish(Fish f){fishList.add(f);}
    
        /**
         * Gets the indicated Fish object from the "tank"
         * @param i the index of the Fish object
         * @return the fish object at the selected index
         */
        public Fish getFish(int i){return fishList.get(i);}
        
        /**
         * Paints the Fish objects and the "tank" in which they swim
         * @param g the graphics context
         */
        @Override
        public void paintComponent(Graphics g)
        {
            Graphics2D g2 = (Graphics2D) g;
            g2.setBackground(Color.blue);
            for(int i = 0; i < fishList.size(); i++)
            {
                g2.setColor(fishList.get(i).getColor());
                g2.draw(fishList.get(i).getFishShape());
                g2.fillPolygon(fishList.get(i).getFishShape());
                this.repaint();
            }
        }
    }
    FishFrame Class:
    Code:
    package fishthreads;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    /**
     *
     */
    public class FishFrame extends JFrame
    {
        FishComponent fc = new FishComponent();
        JPanel fishPanel = new JPanel();
    
        public FishFrame()
        {
            this.setSize(500, 500);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setTitle("Fish Threads");
            fishPanel.add(fc);
            this.add(fishPanel);
        }
    }
    Main Class:
    Code:
    package fishthreads;
    
    /**
     *
     */
    public class Main
    {
        public static void main(String[] args)
        {
            FishFrame ff = new FishFrame();
            ff.setVisible(true);
        }
    }
    The frame displays, and is totally blank, not even the background color displays. Any help pinpointing my error would be greatly appreciated.

    Thanks!

  2. #2
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    Re: JComponent Doesn't Add To JFrame

    The background isn't being drawn because you aren't drawing it. Calling setBackground sets the colour of the background it doesn't draw it, that's up to you to do in the paintComponent method. Also JComponents are transparent by default so if you should be setting it to opaque if you are going to draw a background.

    Having said all that, your FishComponent should really be a FishTank which should extend JPanel and each of your Fish should be JComponents added to the JPanel.

    They probably shouldn't all be on their own threads either, normally one animation thread handling all of the moving objects is sufficient.
    Posting code? Use code tags like this: [code]...Your code here...[/code]
    Click here for examples of Java Code

  3. #3
    Join Date
    Mar 2009
    Posts
    22

    Re: JComponent Doesn't Add To JFrame

    Thanks for the quick reply! I definitely appreciate it.

    I agree 100&#37; with your advice about using one thread instead of multiple, unfortunately the assignment specifically dictates that the fish must each be their own thread.

    Your advice of extending JPanel instead is also good advice which I will implement in my reworking of the program.

    However, I am slightly confused by your discussion of the setBackground() method. It seems that when the repaint() method is called it should be drawn, but is not. My understanding of JComponent must surely be flawed. Would you mind elaborating for clarity?

  4. #4
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    Re: JComponent Doesn't Add To JFrame

    unfortunately the assignment specifically dictates that the fish must each be their own thread.
    Does it really say this or does it say they must be run on their own thread. Making each fish extend from Thread is a really rubbish way of doing this, however if the requirement is that they are run on their own thread your fish can extend JComponent and implement Runnable which makes much more sense.

    However, I am slightly confused by your discussion of the setBackground() method. It seems that when the repaint() method is called it should be drawn, but is not. My understanding of JComponent must surely be flawed. Would you mind elaborating for clarity?
    The drawing of JComponent (like all swing components) is controlled by the UIComponent for the installed L&F but as far as I know for all L&F's JComponent is totally transparent ie it doesn't have a background (or foreground). If you extend JComponent and you want a background you need to set the background colour and call setOpaque(true);. In your paintComponent method if you call super(g) you may well get the background painted (but I'm not 100% not sure about this), if not you have to draw it yourself. The alternative, if you want a background, is to use JPanel which is basically a JComponent with a filled in background.
    Posting code? Use code tags like this: [code]...Your code here...[/code]
    Click here for examples of Java Code

  5. #5
    Join Date
    Mar 2009
    Posts
    22

    Re: JComponent Doesn't Add To JFrame

    Well that certainly clears up my confusion with the JComponent. I'm going to go rework and retinker my program, I'll post back when I get another implementation.

    Thanks again for the input

Posting Permissions

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





Click Here to Expand Forum to Full Width

Featured