I'm trying to make a circle appear from a class I've developed to move following the x co-ordinate of the mouse. I've done that part correctly, it's just loading the class...Can anyone tell me why it isn't loading?

I do love to solve problems myself but I've been working on this for a long time and I think it might be a silly mistake, I'm new to Java so I would really appreciate the help.

class MouseMovedListener implements MouseMotionListener
{
    public void mouseMoved(MouseEvent e)
    {

         xposcounter = e.getX();

         for(int i = 0; i <= grid.length; i++)
         {
              //Get the left hand side position of the grid
              int leftxpos = pCenter.getWidth()/2 - ((GapConstant*(grid.length+6)+(grid.length*rw))/2) + rw*i + GapConstant*i;
              
              //Get the right hand side position of the grid
              int rightxpos = pCenter.getWidth()/2 + ((GapConstant*(grid.length+6)+(grid.length*rw))/2) +rw*i + GapConstant*i;

                    //Show the counter appearing above the columns the mouse is over
                    if(xposcounter > leftxpos && xposcounter < rightxpos)
                    {
                        //Load the circle
                         CircleComponent mycounter = new CircleComponent();
                         
                    }
         }
    }

If you need to see the class code just ask...Thanks in advance for anyone who helps!

Recommended Answers

All 10 Replies

I assume CircleComponent provides a method to draw to a graphics context? Just creating an instance of CircleComponent won't do anything for you by itself. Painting operations for a component will occur in paintComponent(Graphics). This means that your paintComponent() method is going to need access to that CircleComponent object so it can call the appropriate method on it to render to the graphics context. Something like

CircleComponent circle;

public void paintComponent(Graphics g){
  if (circle != null{
    circle.draw(g);
  }
}

Your mouse move handler can then either create a new CircleComponent, or better yet, alter the properties on a single instance as needed, and call repaint()

//Show the counter appearing above the columns the mouse is over
if(xposcounter > leftxpos && xposcounter < rightxpos)
{
   //Load the circle
   circle = new CircleComponent();
    repaint();
 }

This is what I had for my class circle component excluding your if statement:

package mypackage;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.Graphics;
import javax.swing.JComponent;
import java.awt.Color;
import java.awt.geom.Ellipse2D;

public class CircleComponent extends JComponent
{

    public CircleComponent() { }

    private Ellipse2D.Double playerCounter;
    private int xpos1 = 10;
    private int ypos2 = 10;
    private int width = 10;
    private int height = 10;

    public CircleComponent(int w, int h, int x, int y)
    {
        width = w;
        height = h;
        xpos1 = x;
        ypos2 = y;
    }

    public void paintComponent(Graphics g)
    {
        g.setColor (Color.red);
        playerCounter = new Ellipse2D.Double(30,30,30,30);
        setVisible(true);

        if (playerCounter != null){
            playerCounter.draw(g);
        }

    }
}

now I get a connot find symbol error for the .draw part. I think that it because I used Ellipse?

Update for anyone still willing to help:
I've stopped getting the error for the class now but still no moving circle. Heres what I did to get rid of my error. My MouseMove code looks just the same but instead I've added repaint() Please help!

public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;
        g.setColor (Color.red);
        playerCounter = new Ellipse2D.Double(30,30,30,30);
        setVisible(true);

       if (playerCounter != null){
            g2.draw(playerCounter);
        }
    }

Ok, you're doing something quite different than I assumed. I'm not sure how you are placing that component withing whatever container you're using, but the paintComponent() method will need to use the Graphics2D.draw(java.awt.Shape) method to render the ellipse

public void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor (Color.red);
        playerCounter = new Ellipse2D.Double(30,30,30,30);
        g2d.draw(playerCounter);
    }

Your mouseMoved event will need to postion/size that component as needed in the container and then call repaint() for that container.

Edit: Post collision there, you figured out the Graphics2D part I see. How are you placing this component? It will have to be in a container of some sort for it to be rendered.

Ok, you're doing something quite different than I assumed. I'm not sure how you are placing that component withing whatever container you're using, but the paintComponent() method will need to use the Graphics2D.draw(java.awt.Shape) method to render the ellipse

public void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor (Color.red);
        playerCounter = new Ellipse2D.Double(30,30,30,30);
        g2d.draw(playerCounter);
    }

Your mouseMoved event will need to postion/size that component as needed in the container and then call repaint() for that container.

Edit: Post collision there, you figured out the Graphics2D part I see. How are you placing this component? It will have to be in a container of some sort for it to be rendered.

I'm using panels as my container...Will panels work for this? I've replaced the code with your paintComponent code...Still no errors but not working. I've tried placing the actual circle to the center panel using "pCenter.add(mycounter);" and refreshing both in the MouseMoved method and within the public void init() method just in case.

P.S. I've also set my locations of the circle "mycounter = new CircleComponent(xposcounter,ypos,rw,rh);" (xposcounter is the position of the mouse, rw = width, rh = height)

So are you now seeing the circle at all after you have added it to the panel? Note that your paintComponent() method is not actually using the class attributes to create the ellipse, just hard-coded values.

Is there any reason that CircleComponent needs to extend JComponent? You could simply have a draw(Graphics) method in the class which takes the graphics as a parameter (same as it does now) and have your panel's paintComponent() method just call draw() on your CircleComponent and pass along the Graphics reference. This is what I was indicating in the earlier post. You don't have to extend JComponent just to have a method that draws on a graphics context that you pass to it and then you wouldn't have to mess with adding unnecessary components to the panel.

I'm a little lost now. When I get rid of extends JComponent it doesn't like "pCenter.add(mycounter);" but even when I have got that it's not doing anything; not even letting a circle appear. I haven't used the same x,y,h,w attributes as in the class because the variables I want to use are in the main class and it has problems when I try to use them in the separate CircleComponent class. I haven't defined the same variables from the main class into the separate class just in case the value of the variables change.

My center panel doesn't have it's very own paintComponent() method because its just under public ProgramProj() {pNorth = new JPanel(); ...} My application does have its own public void paint (Graphics graf) but I don't know how it can draw the circle based on the x position of the mouse as it needs MouseMoved(MouseEvent e).

I am actually trying to make a connect 4 game where the counter moves above the grid where the mouse is over the grid.

Perhaps if you could post a screen shot of the main screen with a bit of explanation of the component hierarchy it would help. I think you are probably making it more difficult on yourself than it needs to be, but without knowing a little more of the structure I can't recommend too much.

import mypackage.*;

import java.awt.event.*;
import java.awt.*;
import javax.swing.event.MouseInputListener;
import java.awt.event.MouseEvent;

import javax.swing.*;
import java.awt.Color;
import java.awt.Shape;
import java.awt.Rectangle;
import java.awt.geom.Line2D;
import java.awt.geom.Arc2D;
import java.awt.geom.Point2D;

import javax.swing.JApplet;
import javax.swing.*;
import java.awt.Graphics2D;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class ProgramProj extends JFrame implements ActionListener, MouseInputListener
{
    JPanel pNorth;
    JPanel row1;
    JPanel row2;
    JPanel pSouth;
    JPanel pEast;
    JPanel pWest;
    JPanel pCenter;
    JFrame frame;
    CircleComponent mycounter;
    Boolean c;

    Shape[][] grid;  // Grid array
    int rw;          // Grid circles width
    int rh;          // Grid circles height
    int GapConstant; // Gap between each circle in the grid
    int xpos;        // x position of grid
    int ypos;        // y position of grid
    int xcolpos;     // Position of where column chosen
    int ycolpos;     // Position of where column chosen
    int xposcounter;  // Position of the moving counter
    int cypos;
    int leftxpos;
    int rightxpos;
    int counterxpos;

    int[][] x;

/*        if(xcolpos >= xpos -(GapConstant/2) && xcolpos <= xpos + (rw+(GapConstant/2)))
        {
            System.out.println("Column 1");
        }
        else
        {
            System.out.println("Not Column 1");
        }
*/
public class MouseMovedListener implements MouseMotionListener
{
    public void mouseMoved(MouseEvent e)
    {



    }
//http://hivemind.apache.org/hivemind1/hivemind/apidocs/src-html/org/apache/hivemind/HiveMind.html#line.158


    public void mouseDragged(MouseEvent e) {}

}

    public void mouseClicked(MouseEvent e)
    {
        xcolpos = e.getX(); //get the x coordinate after mouse is clicked on the applet
        calculatecolumn();  //call the calculate column method
    }

    public void mouseMoved(MouseEvent e) {

		 xposcounter = e.getX();

		for(int i = 0; i <= grid.length; i++)
		{
			//Center the grid
			leftxpos = pCenter.getWidth()/2 - ((GapConstant*(grid.length)+(grid.length*rw))/2) + rw*i + GapConstant*i;
			rightxpos = leftxpos +rw;

			//Show the counter appearing above the columns the mouse is over
			if(xposcounter >= leftxpos && xposcounter <= rightxpos)
		 		{
				counterxpos = xposcounter;
				mycounter = new CircleComponent(counterxpos, ypos, rw, rh);
				//mycounter.translate(xposcounter, ypos);
				repaint();
				System.out.println(counterxpos);
				c = true;
				//graf.drawOval(leftxpos, ypos, 10, 10);
				//pCenter.add(circle);
				//mycounter.setVisible(true);

		 	}
		         }


		}

 public static void main(String args[])
    {
		new ProgramProj();
	}


    public void mouseExited(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

    public void mouseReleased(MouseEvent e) {}

    public void mousePressed(MouseEvent e) {}

    public void mouseDragged(MouseEvent e) {}

    public ProgramProj()
    {
        setSize(1000,700);
		c = new Boolean(false);
        this.addMouseMotionListener(this);
        this.addMouseListener(this);

        this.setLayout (new BorderLayout());

        pNorth = new JPanel();
        add(pNorth, BorderLayout.NORTH);
        row1 = new JPanel();
        row2 = new JPanel();
        pSouth = new JPanel();
        add(pSouth, BorderLayout.SOUTH);
        pEast = new JPanel();
        add(pEast, BorderLayout.EAST);
        pWest = new JPanel();
        add(pWest, BorderLayout.WEST);
        pCenter = new JPanel();
        add(pCenter, BorderLayout.CENTER);

        pNorth.setLayout (new BorderLayout());
        pNorth.setBackground(Color.white);

        row1.setBackground(Color.white);
        row2.setBackground(Color.white);

        pSouth.setLayout (new BorderLayout());
        pSouth.setBackground(Color.white);

        pEast.setLayout (new BorderLayout());
        pEast.setBackground(Color.white);

        pWest.setLayout (new BorderLayout());
        pWest.setBackground(Color.white);

        pCenter.setLayout (new BorderLayout());
        pCenter.setBackground(Color.white);

        JLabel one = new JLabel("Titles");

        add(pNorth, BorderLayout.NORTH);
        pNorth.add(row1, BorderLayout.NORTH);
        pNorth.add(row2, BorderLayout.SOUTH);

        pNorth.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        pEast.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        pSouth.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        pWest.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        pCenter.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

        JLabel two = new JLabel("a");
        pSouth.add(two);

        JLabel three = new JLabel("a");
        pEast.add(three);

        JLabel four = new JLabel("a");
        pWest.add(four);

        JButton cmdCustomer = new JButton("Add Customer");
        row2.add(cmdCustomer);

        JButton cmdEmployee = new JButton("Add Employee");
        row2.add(cmdEmployee);

        JButton cmdFinance = new JButton("Finance");
        row2.add(cmdFinance);

        JButton cmdDiscounts = new JButton("Discounts");
        row2.add(cmdDiscounts);

        ImageIcon picture = new ImageIcon("mebw.jpg");
        JLabel five = new JLabel(picture);

        pCenter.add(five, BorderLayout.CENTER);

        ///GRID////
        GapConstant = 10;   //Gap between each circle in the grid
        rw = 60;            //Circles width in the grid
        rh = 60;            //Circles height in the grid

        grid = new Shape[6][5];

        x = new int[5][5];

        for(int row = 0; row<5;row++)
        {
            for(int column =0; column<5;column++)
            {
                x[row][column] = 0;

            }
        }

        x[1][3] =1;
        showgrid();

        setVisible(true);//SET APPLICATION FRAME VISIBLE

   }

public void paint (Graphics graf)
    {

        super.paint(graf);

        for(int i = 0; i <= grid.length; i++)
        {
            //Center the grid
            xpos = pCenter.getWidth()/2 - ((GapConstant*(grid.length+6)+(grid.length*rw))/2) + rw*i + GapConstant*i;

            for(int j = 0; j <= grid[0].length; j++)

            {
                ypos = pCenter.getHeight()/2 - ((GapConstant*(grid.length-10)+(grid.length*rh))/2) + rh*j + GapConstant*j;

                //Draw array of ovals
                graf.drawOval(xpos,ypos, rw, rh);
                //Draw vertical lines from right to left
                graf.drawLine(xpos+(rw+GapConstant/2),ypos-GapConstant/2,xpos+(rw+GapConstant/2),ypos+(rh+GapConstant/2));
                //Draw vertical lines from left to right
                graf.drawLine(xpos-(GapConstant/2),ypos-GapConstant/2,xpos-(GapConstant/2),ypos+(rh+GapConstant/2));
                //Draw horizontal lines from top to bottom
                graf.drawLine(xpos-(GapConstant/2),ypos-GapConstant/2,xpos+(rw+GapConstant/2),ypos-GapConstant/2);
                //Draw horitonzal lines from bottom to top
                graf.drawLine(xpos-(GapConstant/2),ypos+(rw+GapConstant/2),xpos+(rw+GapConstant/2),ypos+(rw+GapConstant/2));
            }
        }
    }

class

package mypackage;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.Graphics;
import javax.swing.JComponent;
import java.awt.Color;
import java.awt.geom.Ellipse2D;
import java.awt.BasicStroke;

public class CircleComponent extends JComponent
{

    public CircleComponent() { }

    private int xpos1 = 10;
	private int ypos2 = 10;
	private int width = 10;
	private int height = 10;
	final BasicStroke stroke = new BasicStroke(2.0f);

    public CircleComponent(int w, int h, int x, int y)
    {
		width = w;
		height = h;
		xpos1 = x;
		ypos2 = y;
	}

    public void paintComponent(Graphics g)
    {
		Graphics2D g2 = (Graphics2D) g;
		g2.setStroke(stroke);
        g2.setColor (Color.red);
        //playerCounter = new Ellipse2D.Double(30,30,30,30);
        g2.draw(new Ellipse2D.Double(30,30,30,30));
        setVisible(true);
        repaint();

    }

    private Ellipse2D.Double playerCounter;

}

Thats most of my code, hopefully that'll give you an idea of where I've gone wrong.
Thanks for the help you've given me already.

Ok, this kind of goes in a much different direction than you started, but if you aren't committed to doing the entire thing with your own 2D graphics then leveraging Swing components to do some of the work for you will really reduce a lot of the complexity. This would allow you to concentrate more on the game itself and spend less time doing calculations for the graphics (area calcs, hit testing, etc).

I worked up this example that uses a grid of components that extend JLabel for the board and the "insertion row" (where the player hovers to drop a piece). These components do have custom painting code, but that is the only graphics work that needs to be done. If you are more interested in making the game work than learning the nuances of 2D graphics, I'd recommend going in this direction.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Ellipse2D;
import javax.swing.BorderFactory;
import javax.swing.JLabel;

public class Board extends javax.swing.JFrame {
    InsertPiece[] insertionRow;
    BoardPiece[][] board;
    
    Player currentPlayer;  // player for this turn
    
    static final int ROWS = 5;
    static final int COLS = 6;
    
    public Board() {
        initComponents();
        
        buildBoard();
        setSize(500,500);
        
        currentPlayer = new Player("Smilin Bob", Color.BLUE);
    }
    
    private void buildBoard(){
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx=0;
        gbc.gridy=0;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        gbc.weighty = 1;
        
        // build the insertion row above the board
        insertionRow = new InsertPiece[COLS];
        for (int col=0; col<COLS; col++){
            insertionRow[col] = new InsertPiece(col);
            insertionRow[col].setOpaque(false);
            getContentPane().add(insertionRow[col],gbc);
            gbc.gridx++;
        }
        // build board rows
        board = new BoardPiece[ROWS][COLS];
        for (int i=0; i<ROWS; i++){
            gbc.gridy++;
            gbc.gridx = 0;
            for (int j=0; j<COLS; j++){
                board[i][j] = new BoardPiece();
                board[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
                board[i][j].setOpaque(false);
                getContentPane().add(board[i][j],gbc);
                gbc.gridx++;
            }
        }
        pack();
    }
    
    private void placePiece(int column){
        for(int row = ROWS-1; row >= 0; row--){
            BoardPiece piece = board[row][column];
            if (!piece.isOccupied()){
                piece.setPlayerColor(currentPlayer.getPlayColor());
                piece.setOccupied(true);
                break;
            }
        }
        repaint();
    }
    
    class BoardPiece extends JLabel{
        Color playerColor = Color.RED;
        boolean occupied = false;
        
        public BoardPiece(){
            super();
            Dimension size = new Dimension(50,50);
            setMaximumSize(size);
            setMinimumSize(size);
            setPreferredSize(size);
        }
        
        public void setOccupied(boolean occupied){
            this.occupied = occupied;
        }
        
        public boolean isOccupied(){
            return occupied;
        }
        
        public void setPlayerColor(Color c){
            playerColor = c;
        }
        
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            Ellipse2D.Float ellipse = new Ellipse2D.Float(10,10,getWidth()-20,getHeight()-20);
            if (occupied){
                g2.setColor(playerColor);
                g2.fill(ellipse);
            } else {
                g2.setColor(Color.BLACK);
                g2.draw(ellipse);
            }
        }
    }
    
    class InsertPiece extends JLabel implements MouseListener{
        int column=0;
        boolean filled = false;
        Color textColor = Color.WHITE;
        
        public InsertPiece(int column){
            super();
            this.column = column;
            Dimension size = new Dimension(50,50);
            setMaximumSize(size);
            setMinimumSize(size);
            setPreferredSize(size);
            setHorizontalAlignment(CENTER);
            setForeground(textColor);
            addMouseListener(this);
        }
        
        public void paintComponent(Graphics g){
            if (filled){
                Graphics2D g2 = (Graphics2D)g;
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setColor(currentPlayer.getPlayColor());
                Ellipse2D.Float ellipse = new Ellipse2D.Float(10,10,getWidth()-20,getHeight()-20);
                g2.fill(ellipse);
            }
            // usually want to call super.paintComponent before any custom code
            // but here we want to render the circle first and let the label
            // paint it's text on top of the image
            super.paintComponent(g);
        }

        public void mouseClicked(MouseEvent e) {
            setText(null);
            filled = false;
            placePiece(column);
        }

        public void mousePressed(MouseEvent e) {
            
        }

        public void mouseReleased(MouseEvent e) {
            
        }

        public void mouseEntered(MouseEvent e) {
            setText("1");  // set whatever count you need here
            filled = true;
            repaint();
        }

        public void mouseExited(MouseEvent e) {
            setText(null);
            filled = false;
            repaint();
        }
        
    }    
    
    class Player {
        private String name;
        private Color playColor;
        
        public Player(String name, Color playColor){
            this.name = name;
            this.playColor = playColor;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Color getPlayColor() {
            return playColor;
        }

        public void setPlayColor(Color playColor) {
            this.playColor = playColor;
        }
        
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new java.awt.GridBagLayout());

        pack();
    }// </editor-fold>
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Board().setVisible(true);
            }
        });
    }
    
    // Variables declaration - do not modify
    // End of variables declaration
    
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.