CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Join Date
    Feb 2011
    Posts
    19

    Jpanel + Grid location using MouseListener

    Hi,

    I can't seem to think up a way or can't seem to find an appropriate method in the APIs to help with this.... the problem is as follows;

    I have a grid of JPanels that contain JLabels with randomly assigned background colours, I have MouseListener successfully implemented so far. I have it set up to tell me that if a user clicks anywhere on the Grid it states where it clicks... for example ("Clicked at 534, 60"). However, I was wondering if there is any way to in fact to take the information I gain from the getX() and getY() methods and use it to figure which Panel and Label in the grid I am clicking so I can then run a getBackground() method and compare its background to neighbouring panels.

    Will basically work like a bubble breaker game.

    If my explanation above seems a bit all over the place, just let me know and I'll try clarifying further.

    Thanks for any help offered and if you like, my code thus far is given below:

    first class: GameInterface.java

    Code:
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.border.*;
    import javax.swing.JComponent.*;
    
    public class GameInterface extends JFrame implements ActionListener{
    
    	GridForGame gridForGame = new GridForGame();
    
    
    	public GameInterface(){
    		super("Bubble Breaker");
    		buildGUI();
    		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    		pack();
    		setVisible(true);
    		setResizable(false);
    	}
    	
    	private void buildGUI(){
    		JPanel main = new JPanel(new BorderLayout());
    		add(main, BorderLayout.CENTER);
    		//JLabel statusbar;
    		
    		JPanel menu = new JPanel();
    		menu.setLayout(new BoxLayout(menu, BoxLayout.Y_AXIS));
    		menu.setPreferredSize(new Dimension(150,300));
    		Dimension buttonSize = new Dimension(120,40);
    		
    		addButton("8 x 8 Grid", "small", buttonSize, menu);
    		addButton("12 x 12 Grid", "medium", buttonSize, menu);
    		addButton("16 x 16 Grid", "large", buttonSize, menu);
    		addButton("How To Play", "howToPlay", buttonSize, menu);
    		addButton("Options", "options", buttonSize, menu);
    		addButton("Quit", "quitGame", buttonSize, menu);
    		
    		menu.setBorder(new TitledBorder(new EtchedBorder(4, Color.blue, Color.black), "Menu"));
    		JPanel buttons = new JPanel(new GridLayout(1,1));
    		buttons.add(menu);
    		
    		main.add(buttons, BorderLayout.EAST);
    		main.add(gridForGame, BorderLayout.CENTER);
    		//statusbar = new JLabel("default");
    		//add(statusbar, BorderLayout.EAST);
    		
    	}
    	
    	public void addButton(String label, String command, Dimension size, JPanel panel){
    		
    		JButton button = new JButton(label);
    		button.setPreferredSize(size);
    		button.setMaximumSize(size);
    		Dimension seperatorSize = new Dimension(0,5);
    		button.setAlignmentX(CENTER_ALIGNMENT);
    		button.addActionListener(this);
    		button.setActionCommand(command);
    		panel.add(Box.createRigidArea(seperatorSize));
    		panel.add(button);
    	}
    	
    	public void actionPerformed(ActionEvent ae){
    		
    		String command = ae.getActionCommand();
    		if (command == "small"){
    			gridForGame.small();
    		}
    		
    		if (command == "medium"){
    			gridForGame.medium();
    		}
    		
    		if (command == "large"){
    			gridForGame.large();
    		}
    		
    		if(command.equals("howToPlay")){
    			// check source code for URL that goes here
    		}
    		
    		if(command.equals("options")){
    			// check source image for code that goes here
    		}
    		
    		if(command == "quitGame"){
    			int selectedValue = JOptionPane.showConfirmDialog(null, "If Your Quit The Game All Data Will Be Lost" +
    				"\n" + "Are You Sure You Want To Quit?", "Attention", JOptionPane.YES_NO_OPTION);
    			// Might be issues above due to splitting brackets onto lines
    			
    			if(selectedValue == JOptionPane.NO_OPTION)
    				return;
    			
    			else System.exit(0);
    			
    		}
    	}
    	
    	public static void main( String args[]){
    		GameInterface i = new GameInterface();
    		i.addWindowListener(new WindowAltering());
    	}
    	
    	static class WindowAltering extends WindowAdapter{
    		public void windowClosing(WindowEvent e ){
    			int selectedValue = JOptionPane.showConfirmDialog(null, "Closing This Window Will End the Game." +
    				"\n" + "Click Yes To Exit", "Exit Bubble Breaker Game?", JOptionPane.YES_NO_OPTION);
    			if(selectedValue == JOptionPane.NO_OPTION)
    				return;
    			
    			else System.exit(0);
    		}
    	}
    }
    second/final class : GridForGame.java

    Code:
    import javax.swing.*;
    import javax.swing.border.*;
    import java.awt.*;
    import java.util.Random;
    import java.awt.Color.*;
    import java.awt.Cursor.*;
    import javax.swing.border.*;
    import java.awt.event.*;
    
    public class GridForGame extends JPanel {
    	JTextField myNumberArray[] = new JTextField[16];
    	MouseHandling handler = new MouseHandling();
    	//JLabel statusbar;
    	JLabel statusbar = new JLabel("default");
    
    	public GridForGame(){
    		setLayout(new BorderLayout());
    		setBackground(Color.gray);	
    		setBorder(new EtchedBorder(4, Color.blue, Color.blue));
    		setPreferredSize(new Dimension(600,600));
    	}
    
    	public void small(){
    		JPanel squareContainer = new JPanel();
    		squareContainer.setLayout(new GridLayout(8,8));
    		squareContainer.setPreferredSize(new Dimension(500,500));
    		squareContainer.setMaximumSize(new Dimension(500,500));
    		squareContainer.addMouseListener(handler);
    		statusbar.setText("default");
    		add(statusbar, BorderLayout.NORTH);
    
    		for(int i=0; i<8; i++){
    			JPanel squares = new JPanel();
    			squares.setLayout(new GridLayout(1,1));
    			for(int j=0; j<8; j++){
    				JLabel number = new JLabel();
    				number.setEnabled(true);
    				number.setOpaque(true);
    				//number.setEditable(false);
    				number.setBorder(new MatteBorder(1, 1, 1, 1, Color.black));
    
    				squares.add(number);
    				for(int k=0; k<8; k++){
    					int n = new Random().nextInt(7);
    						switch(n){
    							case 0: number.setBackground(Color.red); break;
    							case 1: number.setBackground(Color.cyan); break;
    							case 2: number.setBackground(Color.blue); break;
    							case 3: number.setBackground(Color.green); break;
    							case 4: number.setBackground(Color.yellow); break;
    							case 5: number.setBackground(Color.magenta); break;
    							default:
    						}	
    					}
    				}
    		
    				squareContainer.add(squares);
    			}
    		add(squareContainer);
    		revalidate();
    	}
    	
    	public void medium(){
    		JPanel squareContainer = new JPanel();
    		squareContainer.setLayout(new GridLayout(12,12));
    		squareContainer.setPreferredSize(new Dimension(500,500));
    		squareContainer.setMaximumSize(new Dimension(500,500));
    		squareContainer.addMouseListener(handler);
    		statusbar.setText("default");
    		add(statusbar, BorderLayout.NORTH);
    
    		for(int i=0; i<12; i++){
    			JPanel squares = new JPanel();
    			squares.setLayout(new GridLayout(1,1));
    			for(int j=0; j<12; j++){
    				JLabel number = new JLabel();
    				number.setEnabled(true);
    				number.setOpaque(true);
    				number.setBorder(new MatteBorder(1, 1, 1, 1, Color.black));
    
    				squares.add(number);
    				for(int k=0; k<12; k++){
    					int n = new Random().nextInt(7);
    						switch(n){
    							case 0: number.setBackground(Color.red); break;
    							case 1: number.setBackground(Color.cyan); break;
    							case 2: number.setBackground(Color.blue); break;
    							case 3: number.setBackground(Color.green); break;
    							case 4: number.setBackground(Color.yellow); break;
    							case 5: number.setBackground(Color.magenta); break;
    							default:
    						}	
    					}
    				}
    		
    				squareContainer.add(squares);
    			}
    		add(squareContainer);
    		revalidate();
    	}
    
    	public void large(){
    		JPanel squareContainer = new JPanel();
    		squareContainer.setLayout(new GridLayout(16,16));
    		squareContainer.setPreferredSize(new Dimension(500,500));
    		squareContainer.setMaximumSize(new Dimension(500,500));
    		squareContainer.addMouseListener(handler);
    		statusbar.setText("default");
    		add(statusbar, BorderLayout.NORTH);
    
    		for(int i=0; i<16; i++){
    			JPanel squares = new JPanel();
    			squares.setLayout(new GridLayout(1,1));
    			for(int j=0; j<16; j++){
    				JLabel number = new JLabel();
    				number.setEnabled(true);
    				number.setOpaque(true);
    				number.setBorder(new MatteBorder(1, 1, 1, 1, Color.black));
    
    				squares.add(number);
    				for(int k=0; k<16; k++){
    					int n = new Random().nextInt(7);
    						switch(n){
    							case 0: number.setBackground(Color.red); break;
    							case 1: number.setBackground(Color.cyan); break;
    							case 2: number.setBackground(Color.blue); break;
    							case 3: number.setBackground(Color.green); break;
    							case 4: number.setBackground(Color.yellow); break;
    							case 5: number.setBackground(Color.magenta); break;
    							default:
    						}	
    					}
    				}
    		
    				squareContainer.add(squares);
    			}
    		add(squareContainer);
    		revalidate();
    	}
    
    	private class MouseHandling implements MouseListener{
    		public void mouseClicked(MouseEvent event){
    			//do stuff here
    			statusbar.setText(String.format("Clicked at %d,%d", event.getX(), event.getY()));
    		}	
    
    		public void mousePressed(MouseEvent event){
    			//do stuff here
    			statusbar.setText("anything");
    		}
    
    		public void mouseReleased(MouseEvent event){
    			//do stuff here
    			statusbar.setText(String.format("Released at %d,%d", event.getX(), event.getY()));
    		}
    
    		public void mouseEntered(MouseEvent event){
    			//do stuff here
    			statusbar.setText("Entered");
    		}
    
    		public void mouseExited(MouseEvent event){
    			//do stuff here
    			statusbar.setText("Exited");
    		}
    	}
    
    }
    Thanks again for any help that could be offered!

  2. #2
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Jpanel + Grid location using MouseListener

    You could add your MouseListener to the panels and labels so that they can report their position or identity directly.

    Or you could iterate over all the panels and labels checking to see if the mouse position is within their bounds. SwingUtilities has methods that simplify point conversions between source and destination coordinate systems, or from screen to component coordinates & vice-versa.

    I think I'd prefer the former option.

    I, myself, have had many failures and I've learned that if you are not failing a lot, you are probably not being as creative as you could be -you aren't stretching your imagination...
    J. Backus
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  3. #3
    Join Date
    Feb 2011
    Posts
    19

    Re: Jpanel + Grid location using MouseListener

    hmmm thats a good idea, thanks, but do you have any idea how i could go from there and actually interrogate them? as in to ask the individual panel what there background is? i know theres a method called getBackground()... but how could i implement this here? i can't seem to think of a way because the loop means that every label has the same name? will I have to change this? or is it still possible based on location?

  4. #4
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Jpanel + Grid location using MouseListener

    Quote Originally Posted by DidierD View Post
    ...do you have any idea how i could go from there and actually interrogate them? as in to ask the individual panel what there background is? i know theres a method called getBackground()... but how could i implement this here? i can't seem to think of a way because the loop means that every label has the same name? will I have to change this? or is it still possible based on location?
    I'm not sure quite what you're trying to achieve. If every panel and label has the mouse listener, the mouseClicked method can just query the source of the click (i.e. the label or panel that was clicked) for its background. No loop is required.

    If you want to identify the label or panel, the label or panel object itself is unique, so can be used to search a list of labels/panels, or you can use Component.setName(..) to give every label/panel a unique name, etc.

    If you could explain clearly what you need to do when a label/panel is clicked, I could be more specific.

    If you can't explain it simply, you don't understand it well enough...
    A. Einstein
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  5. #5
    Join Date
    Feb 2011
    Posts
    19

    Re: Jpanel + Grid location using MouseListener

    Well when each panel/label is clicked I want to retrieve its background colour ( getBackground() )... then compare the results, lets say RED to the panels/labels next to it, and if the colours match, change their colours.

    My issue from my understanding is that I don't know how to question each individual panel/label because they don't seem to be 'unique' at the moment.

    Hope this helps my explanation and thanks again for your help so far!

  6. #6
    Join Date
    Apr 2007
    Posts
    442

    Re: Jpanel + Grid location using MouseListener

    You are in the end using GridLayout to layout the components that would undergo color swapping. You could have the mouse listening in the gridlayouted panel, find out which component was triggered, find out index of that component by iterating over the components in the container. Once done that, you can determine, which indices would be adjacent to it.

    For that you need to check on how GridLayout does the layouting, and remember that orientation might reverse the order. Knowing the index, knowing how many rows & cols your layout has, you should be able to come to a robust solution.

  7. #7
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Jpanel + Grid location using MouseListener

    This is where the Container methods come in handy, especially Container.findComponentAt(..).

    Once a component is clicked, get its X,Y coordinates (or convert the mouse coordinates relative to the container). To find the neighbours, add or subtract the component width or height (including borders, if any) to the X or Y ordinate.

    Ignore co-ordinates that go negative or greater than the container width or height.

    Neighbour to left = (X - width, Y)
    Neighbour to right = (X + width, Y)
    Neighbour above = (X, Y - height)
    Neighbour below = (X, Y + height)

    Once you have a neighbour's co-ordinates, ask the container for the component using Container.findComponentAt(..). Ask the returned component for its background.

    This keeps the calculations independent of the particular layout manager in use.

    YMMV
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  8. #8
    Join Date
    Feb 2011
    Posts
    19

    Re: Jpanel + Grid location using MouseListener

    I think I get what you mean, this will be VERY useful, so thank you VERY VERY much!

    one last thing though, when asking for its background, how would you suggest i go about that? would something along the lines of:

    Container.findComponentAt(..).getBackground();

    would something like that work? first bit finding the component where i clicked and the second part getting the background (obviously).

  9. #9
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Jpanel + Grid location using MouseListener

    On second thoughts, I suggest you use Container.getComponentAt(..). This will return null if there is no component at the supplied point. You should check the return value before trying to get the background.

    In general, it's best to avoid compound statements (e.g. calling a method directly on a return value in a single statement). At least during the development stage, assign the value to a variable before using it. This allows you to put breakpoints or debugging statements in to check the value is what you expect before using it. A decent compiler will optimise out unnecessary variables, so it shouldn't cost anything in code size or speed. Some developers try to be clever and cram as much into a single statement as they can because it looks 'advanced', but it just makes it harder to read, harder to understand, harder to debug, and harder to maintain.

    Programs must be written for people to read, and only incidentally for machines to execute...
    H. Abelson and G. Sussman
    Last edited by dlorde; February 10th, 2011 at 07:56 AM.
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  10. #10
    Join Date
    Feb 2011
    Posts
    19

    Re: Jpanel + Grid location using MouseListener

    Ok thank you so much dude! All this help has been great. Thanks again!

  11. #11
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Jpanel + Grid location using MouseListener

    Quote Originally Posted by DidierD View Post
    Ok thank you so much dude! All this help has been great. Thanks again!
    You're welcome.

    Please call again

    Computer Science is a science of abstraction -creating the right model for a problem and devising the appropriate mechanizable techniques to solve it...
    A. Aho and J. Ullman
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  12. #12
    Join Date
    Feb 2011
    Posts
    19

    Re: Jpanel + Grid location using MouseListener

    Really sorry to ask again so quickly, but i seem to be having a very annoying problem that ive been trying to get around for a few hours....

    I can successfully get the grid location all that... but when using getComponentAt() this much works and I can see the outter most grid I am in, but this causes a problem when I am trying to return the colour of the Label I am clicking for Example:

    for small(){

    I have an 8x8 grid (64)
    inside this grid I have 64 Panels
    and inside each of the Panels I have a label whose background colour is random.

    }

    Now i have tried everything, but i cant seem to get clicking to return the correct colour for that label... I've altered my code many maaaany times, to try and get the grid and panels backgrounds to correspond to background for each panel - this is because the MouseListener seems to get the most outter component when using the getComponentAt(...) method, if you understand what i mean.

    For instance if i click a Label whose background is red, it will return that the background is grey or whatever the background of the grid is instead of the label.

    Any ideas?

  13. #13
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Jpanel + Grid location using MouseListener

    Are you sure you're asking the right container? In the code you add the labels to a panel called squares and add that to a panel called squareContainer (I don't know why). If you ask squareContainer for the component at X, Y, it will always give you the panel called squares...

    Otherwise I'd have to see the revised code.

    Debugging is anticipated with distaste, performed with reluctance, and bragged about forever...
    Anon
    .
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  14. #14
    Join Date
    Feb 2011
    Posts
    19

    Re: Jpanel + Grid location using MouseListener

    Well this is the revised code for small() as its the one im doing my testing on:

    Code:
    public void small(){
    
    		JPanel squareContainer = new JPanel();
            squareContainer.setLayout(new GridLayout(8,8));
            squareContainer.setPreferredSize(new Dimension(500,500));
            squareContainer.setMaximumSize(new Dimension(500,500));
            squareContainer.addMouseListener(handler);
            statusbar.setText("default");
            add(statusbar, BorderLayout.NORTH);
    
            for(int i=0; i<8; i++){
    
                for(int j=0; j<8; j++){
                    JLabel number = new JLabel();
    
                    number.setEnabled(true);
                    number.setOpaque(true);
    
                    number.setBorder(new MatteBorder(1, 1, 1, 1, Color.black));
    
                    for(int k=0; k<8; k++){
                        int n = new Random().nextInt(7);
                            switch(n){
                                case 0: number.setBackground(Color.red);
                                        squareContainer.setBackground(Color.red); break;
                                case 1: number.setBackground(Color.cyan);
                                        squareContainer.setBackground(Color.cyan); break;
                                case 2: number.setBackground(Color.blue);
                                        squareContainer.setBackground(Color.blue); break;
                                case 3: number.setBackground(Color.green);
                                        squareContainer.setBackground(Color.green); break;
                                case 4: number.setBackground(Color.yellow);
                                        squareContainer.setBackground(Color.yellow); break;
                                case 5: number.setBackground(Color.magenta);
                                        squareContainer.setBackground(Color.magenta); break;
                                default:
                            }   
                        }
    
                         squareContainer.add(number);
                    }
            
                }
            add(squareContainer);
            revalidate();
        }
    as you can see, in this version, im just adding the panels to the grid, but it still has the problem as what it does is makes the background of the grid 1 colour at the end ( the colour of the last label set) so when i click on any label, it returns just the 1 background colour.

    and yes i realize and have even tried putting 1 loop of 64 times rather then 8, 8 loops lol xD

    EDIT:

    also, i have tried adding the mouseListener to the Labels themselves, but it still only gets the background colour of its container obviously...

    EDIT AGAIN! :

    Think i may i have solved it...
    simply using findComponentAt(...) instead of getComponentAt(...) - and the find seems to return the corrent colours!
    Last edited by DidierD; February 10th, 2011 at 06:41 PM.

  15. #15
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Jpanel + Grid location using MouseListener

    Well the small() code you posted is adding labels to the grid, not panels.

    I don't know why you're setting the squareContainer background the same as the label background each time - that's redundant.

    When I put the code in, it works fine:
    Code:
    Container panel = (Container) event.getSource();
    Component label = panel.getComponentAt(new Point(event.getX(), event.getY()));
    if (label == null) {
        statusbar.setText("No label here");
        return;
    }
    Color background = label.getBackground();
    In theory, there is no difference between theory and practice, but not in practice...
    Anon.
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

Page 1 of 2 12 LastLast

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