Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 6 of 6

Thread: Issue with mouse listeners in a custom JComponent

  1. #1
    Junior Member
    Join Date
    Nov 2011
    Posts
    19
    My Mood
    Inspired
    Thanks
    1
    Thanked 1 Time in 1 Post

    Default Issue with mouse listeners in a custom JComponent

    I am attemting to make a custom button class by extending JComponent, my code looks like this:

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package com.handuel.marchofthelast.gui;
     
    import com.handuel.marchofthelast.util.ImageUtilities;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.ArrayList;
    import javax.swing.JComponent;
     
    /**
     *
     * @author samuel
     */
    public class NewButton extends JComponent implements MouseListener{
        //the size of the button
        private Dimension size = new Dimension(600, 60);
        //the ArrayList of all ActionListeners added to the button
        private ArrayList<ActionListener> listeners = new ArrayList<ActionListener>();
        //the image to be drawn, this will be made as a subImage of buttons
        private BufferedImage image;
        //the buffered image for my file that contains all my button images
        private BufferedImage buttons;
        private BufferedImage textImage;
        //these are used for the setImage method, instead of rembering the values, just use these constants and pass them in as parameters when method is called
        private static final int ROLLED_OVER_STATE = 0;
        private static final int PRESSED_STATE = 1;
        private static final int DEFAULT_STATE = 2;
        //constructor, takes in the text to display on the button
        public NewButton(String text){
            //methods in the superclass that set everything up correctly and add my mouse listener so the roll over image works correctly
            enableInputMethods(true);   
            addMouseListener(this);
            setFocusable(true);
            /*loads the file with all by button images in and set's it equal to buttons, the ImageUtilities class has some simple static methods usefull for loading text as an image from my font.png,
             easy loading of images, without having to remember the relatively long line of code each time I want to load an image*/
            try{
                buttons = ImageUtilities.loadBitmap("/images/gui/Clickboxes.png");
            }catch(IOException e){
                e.printStackTrace();
            }
            //sets the image to be drawn equal to the default button image located in the buttons bufferedimage
            image = buttons.getSubimage(30, 30, 600, 60);
            //loads our textImage from the parameter passed in the constructor
            try {
                textImage = ImageUtilities.loadTextAsImage(text);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //draws the text image onto the button image
            Graphics g = image.getGraphics();
            g.drawImage(textImage, (image.getWidth()/2)-(textImage.getWidth()/2), (image.getHeight()/2)-(textImage.getHeight()/2), null);
            //sets size equal to the size of the button
            size = new Dimension(600, 60);
        }
        //paints the image at the coordinates 0,0 in the component (the button)
        @Override
        public void paintComponent(Graphics g){
            g.drawImage(image, 0, 0, null);
     
        }
        //adds an ActionListener to our ArrayList, this will be cycled through, calling the actionPerformed method for each ActionListener when the button is clicked
        public void addActionListener(ActionListener e){
            listeners.add(e);
        }
        //changes the image to the default, rolledover or pressed image
        private void setImage(int state){
            switch(state){
                case DEFAULT_STATE:
                    image = buttons.getSubimage(30, 30, 600, 60);
                    break;
                case ROLLED_OVER_STATE:
                    image = buttons.getSubimage(29, 207, 600, 60);
                    break;
                case PRESSED_STATE:
                    image = buttons.getSubimage(29, 115, 600, 60);
                    break;
                default:
                    return;
            }
            //draws the text back on the image
            Graphics g = image.getGraphics();
            g.drawImage(textImage, (image.getWidth()/2)-(textImage.getWidth()/2), (image.getHeight()/2)-(textImage.getHeight()/2), null);
           //repaints the component
            repaint();
        }
        //allows the user to change the text on the button after it has been added
        public void setText(String text){
            try {
                textImage = ImageUtilities.loadTextAsImage(text);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            //repaints the component
            repaint();
        }
        //calls the actionPerformed method for all the ActionListeners
        private void notifyListeners(MouseEvent e){
            ActionEvent evt = new ActionEvent(this,ActionEvent.ACTION_PERFORMED,new String(),e.getWhen(),e.getModifiers());
            synchronized(listeners){
                for (int i = 0; i < listeners.size(); i++){
                    ActionListener tmp = listeners.get(i);
                	tmp.actionPerformed(evt);
                }
            }
        }
        @Override
        public void mouseClicked(MouseEvent me) {
     
        }
       //sets the image to the pressed image
        @Override
        public void mousePressed(MouseEvent me) {
                setImage(PRESSED_STATE);
        }
        //sets the image back to the rolled over state after it has been pressed, also notifys the listeners that a click has occured
        @Override
        public void mouseReleased(MouseEvent me) {
     
                setImage(ROLLED_OVER_STATE);
                notifyListeners(me);
     
        }
        //sets the image to the rolled over image
        @Override
        public void mouseEntered(MouseEvent me) {
            setImage(ROLLED_OVER_STATE);
        }
        //sets the image to the default image
        @Override
        public void mouseExited(MouseEvent me) {
            setImage(DEFAULT_STATE);
        }
        //methods to make sure the image is always at the correct size
        @Override
        public Dimension getPreferredSize(){
            return new Dimension(size.width, size.height);
        }
        @Override
        public Dimension getMaximumSize(){
            return getPreferredSize();
        }
        @Override
        public Dimension getMinimumSize(){
            return getPreferredSize();
        }
    }
    This should hopefully detect when the image is rolled over etc, and set the image accordingly. However, when I add it to a frame like so:
    public class Test extends JFrame{
        public Test(){
            NewButton test = new NewButton("test");
            add(test);
        }
        public static void main(String args[]){
            Test test = new Test();
            test.setDefaultCloseOperation(EXIT_ON_CLOSE);
            test.setSize(800, 300);
            test.setVisible(true);
        }
    }

    The image changes whenever I enter my mouse into the frame or click inside the frame, not the button. Does anyone know why this happens.


  2. #2
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,140
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Issue with mouse listeners in a custom JComponent

    You need to post the code for the ImageUtilities class for testing.

  3. #3
    Administrator copeg's Avatar
    Join Date
    Oct 2009
    Location
    US
    Posts
    5,318
    Thanks
    181
    Thanked 833 Times in 772 Posts
    Blog Entries
    5

    Default Re: Issue with mouse listeners in a custom JComponent

    It is an issue with the LayoutManager. By default, the Content Pane of a JFrame will use a BorderLayout, which can stretch a component to fill the necessary space. Fix would be to use the appropriate LayoutManager and set the preferred size of the Component (for instance, set the layout of the parent Component of NewButton to a FlowLayout, and set the preferred size of NewButton as appropriate)

  4. #4
    Junior Member
    Join Date
    Nov 2011
    Posts
    19
    My Mood
    Inspired
    Thanks
    1
    Thanked 1 Time in 1 Post

    Default Re: Issue with mouse listeners in a custom JComponent

    Thankyou very much for the quick replies I will try copegs answer, but while I do that, here is the code for the ImageUtilities class norm:
    public class ImageUtilities {
     
        public static BufferedImage loadBitmap(String fileName) throws IOException {
            BufferedImage image = null;
            try {
                image = ImageIO.read(ImageUtilities.class.getResource(fileName));
            } catch (IOException e) {
                throw (e);
            }
            return image;
        }
     
        public static BufferedImage loadTextAsImage(String text) throws IOException {
            int charWidth = 20, charHeight = 20;
            BufferedImage font = null;
     
     
            try {
                font = loadBitmap("/images/text_1.png");
            } catch (IOException e) {
                throw (e);
            }
            BufferedImage textImage = new BufferedImage(text.length() * charWidth, charHeight, BufferedImage.TRANSLUCENT);
            Graphics g = textImage.getGraphics();
            for(int i = 0; i < text.length();i++){
                BufferedImage letter = font.getSubimage(getLocation(text.charAt(i)).x, getLocation(text.charAt(i)).y, charWidth, charHeight);
                g.drawImage(letter, i * charWidth, 0, null);
            }
            return textImage;
        }
     
        private static Point getLocation(char c) {
            switch (c) {
                case 'a':
                    return new Point(0, 20);
                case 'b':
                    return new Point(20, 20);
                case 'c':
                    return new Point(40, 20);
                case 'd':
                    return new Point(60, 20);
                case 'e':
                    return new Point(80, 20);
                case 'f':
                    return new Point(100, 20);
                case 'g':
                    return new Point(120, 20);
                case 'h':
                    return new Point(140, 20);
                case 'i':
                    return new Point(160, 20);
                case 'j':
                    return new Point(180, 20);
                case 'k':
                    return new Point(200, 20);
                case 'l':
                    return new Point(220, 20);
                case 'm':
                    return new Point(240, 20);
                case 'n':
                    return new Point(260, 20);
                case 'o':
                    return new Point(280, 20);
                case 'p':
                    return new Point(300, 20);
                case 'q':
                    return new Point(320, 20);
                case 'r':
                    return new Point(340, 20);
                case 's':
                    return new Point(360, 20);
                case 't':
                    return new Point(380, 20);
                case 'u':
                    return new Point(400, 20);
                case 'v':
                    return new Point(420, 20);
                case 'w':
                    return new Point(440, 20);
                case 'x':
                    return new Point(460, 20);
                case 'y':
                    return new Point(480, 20);
                case 'z':
                    return new Point(500, 20);
                case 'A':
                    return new Point(0, 0);
                case 'B':
                    return new Point(20, 0);
                case 'C':
                    return new Point(40, 0);
                case 'D':
                    return new Point(60, 0);
                case 'E':
                    return new Point(80, 0);
                case 'F':
                    return new Point(100, 0);
                case 'G':
                    return new Point(120, 0);
                case 'H':
                    return new Point(140, 0);
                case 'I':
                    return new Point(160, 0);
                case 'J':
                    return new Point(180, 0);
                case 'K':
                    return new Point(200, 0);
                case 'L':
                    return new Point(220, 0);
                case 'M':
                    return new Point(240, 0);
                case 'N':
                    return new Point(260, 0);
                case 'O':
                    return new Point(280, 0);
                case 'P':
                    return new Point(300, 0);
                case 'Q':
                    return new Point(320, 0);
                case 'R':
                    return new Point(340, 0);
                case 'S':
                    return new Point(360, 0);
                case 'T':
                    return new Point(380, 0);
                case 'U':
                    return new Point(400, 0);
                case 'V':
                    return new Point(420, 0);
                case 'W':
                    return new Point(440, 0);
                case 'X':
                    return new Point(460, 0);
                case 'Y':
                    return new Point(480, 0);
                case 'Z':
                    return new Point(500, 0);
                case '1':
                    return new Point(0, 40);
                case '2':
                    return new Point(20, 40);
                case '3':
                    return new Point(40, 40);
                case '4':
                    return new Point(60, 40);
                case '5':
                    return new Point(80, 40);
                case '6':
                    return new Point(100, 40);
                case '7':
                    return new Point(120, 40);
                case '8':
                    return new Point(140, 40);
                case '9':
                    return new Point(160, 40);
                case '0':
                    return new Point(180, 40);
                case '!':
                    return new Point(200, 40);
                case '*':
                    return new Point(220, 40);
                case '(':
                    return new Point(240, 40);
                case ')':
                    return new Point(260, 40);
                case '?':
                    return new Point(280, 40);
                case '.':
                    return new Point(300, 40);
                case ',':
                    return new Point(320, 40);
                case '@':
                    return new Point(340, 40);
                case '#':
                    return new Point(360, 40);
                default:
                    return new Point(500, 40);
            }
        }
    }

  5. #5
    Junior Member
    Join Date
    Nov 2011
    Posts
    19
    My Mood
    Inspired
    Thanks
    1
    Thanked 1 Time in 1 Post

    Default Re: Issue with mouse listeners in a custom JComponent

    Thankyou very much copeg, changing the layout manager does indeed fix the problem. For refference for any with a similar problem, to fix it all I had to do was edit my test class(my main class), so it was like this:
    public class Test extends JFrame{
        public Test(){
            setLayout(new FlowLayout());
            NewButton test = new NewButton("test");
            test.setPreferredSize(new Dimension(600, 50));
            add(test);
        }
        public static void main(String args[]){
            Test test = new Test();
            test.setDefaultCloseOperation(EXIT_ON_CLOSE);
            test.setSize(800, 300);
            test.setVisible(true);
        }
    }
    As apposed to what it looked like originally which can be seen in my first post.

  6. #6
    Super Moderator Norm's Avatar
    Join Date
    May 2010
    Location
    Eastern Florida
    Posts
    25,140
    Thanks
    65
    Thanked 2,720 Times in 2,670 Posts

    Default Re: Issue with mouse listeners in a custom JComponent

    To see what the size of the component is, add this to the paintComponent method:
    System.out.println("pC bnds=" + getBounds());

Similar Threads

  1. Listeners not working!
    By Alex-Green in forum Member Introductions
    Replies: 1
    Last Post: February 19th, 2012, 07:49 PM
  2. Serializing Listeners
    By aussiemcgr in forum Java Theory & Questions
    Replies: 1
    Last Post: March 11th, 2011, 05:47 PM
  3. Mouse Listeners
    By newbie in forum AWT / Java Swing
    Replies: 2
    Last Post: November 27th, 2010, 11:08 PM
  4. Action Listeners and Key Listeners Help
    By xctive in forum What's Wrong With My Code?
    Replies: 3
    Last Post: November 18th, 2010, 09:27 AM
  5. Listeners, CopyOnWriteArrayList and removals
    By Richard in forum Collections and Generics
    Replies: 2
    Last Post: August 5th, 2010, 02:12 PM

Tags for this Thread