Search code examples
javaswingjbuttonencapsulation

Move JButton setup to separate class


I have a loop that creates a series of JButtons. This code is buried deep inside a class that is primarily concerned with multi-threading, so it uses Executors, Callables, Futures, etc. I'm trying to keep this class fairly encapsulated, so I want to move the work of setting up the JButton to its own class. This is the body of my loop where it creates a single button. It works just fine:

    JButton imageButton = new JButton(new ImageIcon(image));
    imageButton.setMinimumSize(imageSize);
    imageButton.setPreferredSize(imageSize);
    imageButton.setMaximumSize(imageSize);
    imageButton.setVisible(true);

    imageButton.addMouseMotionListener(new MouseMotionListener() {
        @Override
        public void mouseDragged(java.awt.event.MouseEvent mouseEvent) {
            // do a bunch of stuff          }
        }

        @Override
        public void mouseMoved(java.awt.event.MouseEvent mouseEvent) {}
    });

    imagesPanel.add(imageButton);

This is only going to get messier, so here is my attempt to move it to a separate class:

ImageButton imageButton = new ImageButton(image, imageSize);
imageButton.addMouseMotionListener();
imagesPanel.add(imageButton);

And this is my class:

public class ImageButton extends JButton {

    JButton button;
    static final long serialVersionUID = 1;

    public ImageButton(Image image, Dimension imageSize) {
        button = new JButton(new ImageIcon(image));
        button.setMinimumSize(imageSize);
        button.setPreferredSize(imageSize);
        button.setMaximumSize(imageSize);
        button.setVisible(true);
    }

    public void addMouseMotionListener() {
        button.addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseDragged(java.awt.event.MouseEvent mouseEvent) {
                // do a bunch of stuff
            }

            @Override
            public void mouseMoved(java.awt.event.MouseEvent mouseEvent) {}
        });
    }   
}

This all compiles without error, for whatever that is worth. The buttons layout in their proper sizes and proper places. However, the images do not appear (the buttons are blank) and the mouse listener is not functioning. Can anyone see what I am doing wrong and how to make this work?


Solution

  • Your ImageButton class is wrong. You're holding an unnecessary instance to JButton inside. So, the implementation should be:

    public class ImageButton extends JButton {
    
        static final long serialVersionUID = 1;
    
        public ImageButton(Image image, Dimension imageSize) {
            super(new ImageIcon(image));
            this.setMinimumSize(imageSize);
            this.setPreferredSize(imageSize);
            this.setMaximumSize(imageSize);
            this.setVisible(true);
        }
    
        public void addMouseMotionListener() {
            this.addMouseMotionListener(new MouseMotionListener() {
                @Override
                public void mouseDragged(java.awt.event.MouseEvent mouseEvent) {
                    // do a bunch of stuff
                }
    
                @Override
                public void mouseMoved(java.awt.event.MouseEvent mouseEvent) {}
            });
        }   
    }
    

    This way, you're setting the parameters to the class instead to a member, and all instances of ImageButton will have the same configuration.