Results 1 to 11 of 11
  1. #1
    AcousticBruce is offline Senior Member
    Join Date
    Dec 2010
    Location
    Indiana
    Posts
    202
    Rep Power
    4

    Default I am stumped trying to relate a Grpahic background to a matrix.

    I am trying to get a MouseListener to add 1 to the board[][] on the correct tile. I am just having issue and it is probably because I have been coding so long today. My issue is the pixels are off a little bit and get worse the farther away from [0][0] I get.

    the getX() - 8 and getY() - 30 is because of the JFrame default window.



    i have 3 arguments that create a grid background.
    tileNumber - is how big the grid is squared.
    tileSize - is how big to draw each square.
    grout - is how many pixels in between the boxes.

    the calculation to draw is
    Java Code:
            int tWidth = row * tileSize + grout;
            int tHeight = col * tileSize + grout;
            if (board[row][col] == 0) {
                        g.setColor(tileColor);
                        g.fillRect(tWidth, tHeight, tileSize-grout, tileSize-grout);
                    }


    It is Very close, but I cannot figure out why this is off.

    Java Code:
    public void mouseClicked(MouseEvent event) {
            int x = (int)(event.getX()-8) / (gameWindow.tileSize + gameWindow.grout);
            int y = (int)(event.getY()-30) / (gameWindow.tileSize + gameWindow.grout);
            System.out.printf("\n\n[][] " + x + ":" + y + "\n     " + event.getX() + ":" + event.getY());
            gameWindow.board[x][y] += 1;
            gameWindow.repaint();
        };

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

    Default

    Quote Originally Posted by AcousticBruce View Post
    the getX() - 8 and getY() - 30 is because of the JFrame default window.
    This suggests to me that you're adding the MouseListener to the JFrame, which you probably shouldn't be doing. You're probably better off adding it to a component held by the JFrame such as its contentPane or whichever component draws the grid.


    i have 3 arguments that create a grid background.
    tileNumber - is how big the grid is squared.
    tileSize - is how big to draw each square.
    grout - is how many pixels in between the boxes.

    the calculation to draw is ...
    Any chance of creating and posting an SSCCE for this? This type of question is tailor made for the SSCCE construct.

    Much luck.

  3. #3
    AcousticBruce is offline Senior Member
    Join Date
    Dec 2010
    Location
    Indiana
    Posts
    202
    Rep Power
    4

    Default

    I had to google SSCCE, I have learned something new :)

    I deleted TONS of code for this post, but I kept them as separate classes. Hopefully this isnt too much.


    *******Main*******
    Java Code:
    public class Main {
    
        public static void main(String[] args)	{
            new Frame();
        }
    }


    *******Frame*******
    Java Code:
    import javax.swing.JFrame;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseEvent;
    
    public class Frame extends JFrame implements MouseListener{
    
        private Grid gameWindow = new Grid();
    
        Frame() {
            super("Grid");
            int tm = gameWindow.tileNumber;
            int ts = gameWindow.tileSize;
            int g = gameWindow.grout;
            int width = (tm*ts+g)+16;
            int height = (tm*ts+g)+38;
            setSize(width, height);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            addMouseListener(this);
            add(gameWindow);
            setVisible(true);
    
        }
        // **** MOUSE LISTENERS **** //
        public void mouseClicked(MouseEvent event) {
            int x = (int)(event.getX()-8) / (gameWindow.tileSize + gameWindow.grout);
            int y = (int)(event.getY()-30) / (gameWindow.tileSize + gameWindow.grout);
            gameWindow.board[x][y] += 1;
            gameWindow.repaint();
        };
    
        public void mousePressed(MouseEvent event) {};
        public void mouseReleased(MouseEvent event) {};
        public void mouseEntered(MouseEvent event) {};
        public void mouseExited(MouseEvent event) {};
    }


    *******Grid*******
    Java Code:
    import javax.swing.JPanel;
    import java.awt.Graphics;
    import java.awt.Color;
    import java.util.Random;
    
    public class Grid extends JPanel {
    
        public int tileNumber = 20, tileSize = 20, grout = 1;
        public int[][] board = new int[tileNumber][tileNumber];
        private Random rand = new Random();
    
    
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            this.setBackground(Color.BLACK);
    
            //****************Draw board****************
            for (int row = 0; row < board.length; row++) {
                for (int col = 0; col < board.length; col++) {
    
                    int tWidth = row * tileSize + grout;
                    int tHeight = col * tileSize + grout;
    
                    //Draw background squares
                    if (board[row][col] == 0) {
                        g.setColor(Color.WHITE);
                        g.fillRect(tWidth, tHeight, tileSize-grout, tileSize-grout);
                    }
                    if (board[row][col] > 0) {
                        g.setColor(Color.RED);
                        g.fillRect(tWidth, tHeight, tileSize - grout, tileSize - grout);
                    }
                }
            }
        }
    }

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

    Default

    You're in luck as I created an SSCCE myself since I didn't see yours! (d'oh!)

    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class GameWindowGrid extends JPanel {
       private static final int MAX_ROW = 8;
       private static final int MAX_COL = 8;
       private int tileSize = 30;
       private int grout = 2;
       private Color tileColor = Color.pink;
       private int[][] board = new int[MAX_ROW][MAX_COL];
    
       public GameWindowGrid() {
          setPreferredSize(new Dimension(MAX_COL * tileSize + grout, MAX_ROW * tileSize + grout));
          addMouseListener(new MouseAdapter() {
    
             public void mousePressed(MouseEvent event) {
                int x = (int) (event.getX() - 8) / (tileSize + grout); // *****
                int y = (int) (event.getY() - 30) / (tileSize + grout);  // *****
    
                board[x][y] += 1;
                repaint();
             }
          });
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          for (int row = 0; row < MAX_ROW; row++) {
             for (int col = 0; col < MAX_COL; col++) {
                int tWidth = row * tileSize + grout;
                int tHeight = col * tileSize + grout;
                if (board[row][col] == 0) {
                   g.setColor(tileColor);
                   g.fillRect(tWidth, tHeight, tileSize - grout, tileSize - grout);
                }
             }
          }
       }
    
       private static void createAndShowUI() {
          JFrame frame = new JFrame("GameWindowGrid");
          frame.getContentPane().add(new GameWindowGrid());
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }

    And the problem is where I've commented the code with // *****. At that location you use tileSize + grout in the denominator as if it were the width of each grid square, but it's not. The true width (and height) of each square is tileSize alone as simple math will show you. If you take this into consideration, the MouseListener works better with the following changes:

    Java Code:
             public void mousePressed(MouseEvent event) {
                // int x = (int) (event.getX() - 8) / (tileSize + grout);
                // int y = (int) (event.getY() - 30) / (tileSize + grout);
    
                int x = (int) (event.getX()) / (tileSize);
                int y = (int) (event.getY()) / (tileSize);
    
                board[x][y] += 1;
                repaint();
             }
          });

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

    Default

    Yeah, the same changes to your code works as well...

    Java Code:
          Frame() {
             super("Grid");
             int tm = gameWindow.tileNumber;
             int ts = gameWindow.tileSize;
             int g = gameWindow.grout;
             int width = (tm * ts + g) + 16;
             int height = (tm * ts + g) + 38;
             setSize(width, height);
             setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             //!! addMouseListener(this); // don't add MouseListener to JFrame!
             
             // Instead add it to the Grid object.
             gameWindow.addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent e) {
                   myMousePressed(e);
                }
             });
             add(gameWindow);
             setVisible(true);
          }
    
          // again, grout should not be in the demoninator 
          private void myMousePressed(MouseEvent e) {
             int x = (int) (e.getX()) / (gameWindow.tileSize);
             int y = (int) (e.getY()) / (gameWindow.tileSize);
             gameWindow.board[x][y] += 1;
             gameWindow.repaint();
          };
    Again, don't add the MouseListener to the JFrame. Add it to the component doing the drawing. That way the x and y from the Point returned by the MouseEvent object matches exactly the x and y of the graphic. Again, grout has no business being in the denominator of your equation.

  6. #6
    AcousticBruce is offline Senior Member
    Join Date
    Dec 2010
    Location
    Indiana
    Posts
    202
    Rep Power
    4

    Default

    It makes sense about the JFrame and the listenere.

    Is it ok to implement the MouseListener a seperate class then the graphics? I am not having luck unless I need to implement it in the graphics class also.
    Java Code:
    gameWindow.addMouseListener(this); [COLOR="Red"]// This causes the Listener to be off.[/COLOR]
    
    *** instead of 
    
    this.addMouseListener(this); [COLOR="Red"]// This works [/COLOR]


    ******

    Also I am lost on the grout issue. Grout was much needed for this code.
    Java Code:
    int tWidth = row * tileSize + grout;
                    int tHeight = col * tileSize + grout;
    
    
                    //Draw background squares
                    if (board[row][col] == 0) {
                        g.setColor(tileColor);
                        g.fillRect(tWidth, tHeight, tileSize-grout, tileSize-grout);
                    }

    So why would it not be needed in the MouseListener code?
    Last edited by AcousticBruce; 01-16-2011 at 05:14 AM.

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

    Default

    Quote Originally Posted by AcousticBruce View Post
    It makes sense about the JFrame and the listenere.

    Is it ok to implement the MouseListener a seperate class then the graphics?
    Java Code:
    gameWindow.addMouseListener(this);
    
    *** instead of 
    
    this.addMouseListener(this);
    Yes, absolutely. But even better still is to never have your MouseListener as as "this" -- don't have your GUI class implement MouseListener as it doesn't scale well. Instead you're far better off using either an anonymous inner class, or a private inner class, or a stand-alone listener class.


    Also I am lost on the grout issue. Grout was much needed for this code.
    Java Code:
                    int tWidth = row * tileSize + grout;
                    int tHeight = col * tileSize + grout;
    
    
                    //Draw background squares
                    if (board[row][col] == 0) {
                        g.setColor(tileColor);
                        g.fillRect(tWidth, tHeight, tileSize-grout, tileSize-grout);
                    }

    So why would it not be needed in the MouseListener code?
    It's nothing but basic arithmetic. The key is what is the width and height of each cell? Let's take width which is the distance of the start of one cell to the next, or tWidth for the (i + 1) row minus the tWidth of the i-th row.

    true width = ((i + 1) * tileSize + grout) - (i * tileSize + grout)

    factored out:
    true width = i * tileSize + tileSize + grout - i * tileSize - grout

    rearranged:
    true width = i * tileSize - i * tileSize + tileSize + grout - grout

    group together:
    true width = (i * tileSize - i * tileSize) + tileSize + (grout - grout)

    do the basic math:
    true width = (0) + tileSize + (0)

    true width = tileSize

    Also logically, grout is not added to each tile but only once, more of as a padding in the beginning of the cell.


    edit: also, if you had done this:
    Java Code:
    int tWidth = row * (tileSize + grout);
    Then it would be a different story, and you'd want grout in the denominator.
    Last edited by Fubarable; 01-16-2011 at 05:22 AM.

  8. #8
    AcousticBruce is offline Senior Member
    Join Date
    Dec 2010
    Location
    Indiana
    Posts
    202
    Rep Power
    4

    Default

    Fubarable this makes sense with the mouse listener, thank you. As far as grout I will look into the math.


    Instead you're far better off using either an anonymous inner class, or a private inner class, or a stand-alone listener class.
    Is there a difference in a stand-alone vs an inner class?
    Is there a reason why you would chose inner vs stand-alone other then organization?

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

    Default

    I would choose an inner class if its functionality is closely tied to the class and neither is quite big. I would choose a stand alone class if the above is not true, or if there's a chance of using the listener code elsewhere or possible or chance that the listener code may change independent from the GUI.

  10. #10
    AcousticBruce is offline Senior Member
    Join Date
    Dec 2010
    Location
    Indiana
    Posts
    202
    Rep Power
    4

    Default

    I tried to make a new class for Listeners, but I am not having luck getting the Keylistener to work. Is there something I am missing?

    Java Code:
    import javax.swing.JFrame;
    import java.awt.event.*;
    
    public class FrameSet extends JFrame{
    
        public HungarySnake gameWindow = new HungarySnake();
    
        FrameSet() {
            super("Snake Game!");
            int tn = gameWindow.tileNumber;
            int ts = gameWindow.tileSize;
            int g = gameWindow.grout;
            int width = (tn*ts+g);
            int height = (tn*ts+g);
            setSize(width, height);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    	//Adding listeners.
    	Handlers handle = new Handlers();
            gameWindow.addKeyListener(handle);
            gameWindow.addMouseListener(handle);
    
    	add(gameWindow);
            setVisible(true);
    
        }
    
        private class Handlers implements KeyListener, MouseListener {
    
        	// **** MOUSE LISTENERS ***** //
    		public void mousePressed(MouseEvent event) {
                    [COLOR="Red"]System.out.println("Event Happened!");[/COLOR]}                    // This works!
    		public void mouseReleased(MouseEvent event) {}
    		public void mouseClicked(MouseEvent event) {}
    		public void mouseEntered(MouseEvent event) {}
    		public void mouseExited(MouseEvent event) {}
    
    
    	    // ***** KEY LISTENERS ***** //
    	    public void keyPressed(KeyEvent event){
    	        gameWindow.move(event.getKeyCode());
    	        [COLOR="Red"]System.out.println("Event Happened!");[/COLOR]                      // This does NOT work!?!?
    	    }
    	    public void keyReleased(KeyEvent event){}
    	    public void keyTyped(KeyEvent event){}
    	}
    }
    Last edited by AcousticBruce; 01-17-2011 at 10:23 PM.

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

    Default

    KeyListeners only work in components that have the focus, and so are you sure that the component that you've added it to has focus? It's often better to use key binding rather than key listeners as the tutorials will explain.

Similar Threads

  1. help in matrix
    By Engineer in forum New To Java
    Replies: 7
    Last Post: 10-06-2010, 01:26 PM
  2. stumped......
    By trueblue in forum New To Java
    Replies: 21
    Last Post: 07-13-2009, 04:16 PM
  3. Relate JTextfield with glasspane to glasspane
    By finzaiko in forum AWT / Swing
    Replies: 1
    Last Post: 04-30-2009, 05:09 AM
  4. Relate Thread and resultSet
    By HuanManwe in forum Threads and Synchronization
    Replies: 14
    Last Post: 02-15-2009, 09:12 PM
  5. Help with matrix
    By susan in forum New To Java
    Replies: 1
    Last Post: 08-07-2007, 04:37 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
  •