javaswingbuttonjframenetbeans-12

Is there a way to automatically edit button's properties in Java JFrame?


I've set following properties for one of my buttons.

try {
    name.setIcon(new javax.swing.ImageIcon(ImageIO.read(newFile("./src/main/java/resorces/Default.png"))));
} catch (IOException ex) {
    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
name.setBorderPainted(false); 
name.setContentAreaFilled(false); 
name.setFocusPainted(false); 
name.setOpaque(false);

My problem is that I have a bunch of buttons just like this one. I was wondering if it's possible to make a method that would take in button's name and set all the properties for me.

Example:

public void SetProperties(??? x){
    try {
        x.setIcon(new javax.swing.ImageIcon(ImageIO.read(newFile("./src/main/java/resorces/Default.png"))));
    } catch (IOException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
    x.setBorderPainted(false); 
    x.setContentAreaFilled(false); 
    x.setFocusPainted(false); 
    x.setOpaque(false);
}

Thanks for help!


Solution

  • You could...

    Use a "builder pattern"

    The concept is to provide a workflow which allows you to apply all the properties you want and then have that object "built", for example...

    public class ButtonBuilder<Builder extends ButtonBuilder<Builder>> {
        private JButton button;
    
        public ButtonBuilder() {
            button = new JButton();
        }
        
        public Builder withText(String text) {
            button.setText(text);
            return (Builder)this;
        }
        
        public Builder withIcon(Icon icon) {
            button.setIcon(icon);
            return (Builder)this;
        }
        
        public Builder borderPainted(boolean painted) {
            button.setBorderPainted(painted);
            return (Builder)this;
        }
        
        public Builder contentAreaFilled(boolean painted) {
            button.setContentAreaFilled(painted);
            return (Builder)this;
        }
        
        public Builder focusPainted(boolean painted) {
            button.setFocusPainted(painted);
            return (Builder)this;
        }
        
        public JButton build() {
            return button;
        }
    }
    

    nb: Note, a common pattern for a builder is store the properties in some kind of cache/lookup, which are then applied when you call build, but in this case, it's just easier to apply them directly to the button itself

    nb: Obviously, I've only supplied a small subset of properties you might want to specify for a button, you'll need to add the rest ;)

    And then you can build the button using something like...

    JButton happyButton = new ButtonBuilder()
            .withText("Happy")
            .withIcon(new ImageIcon(ImageIO.read(getClass().getResource("/images/happy.png"))))
            .borderPainted(false)
            .focusPainted(false)
            .contentAreaFilled(false)
            .build();
    

    But that's not what I asked, I don't want to have to have reapply the all the properties each time I want to create a button

    Yes, I know, I was getting to it. Once you have a "base" builder, you could make one or more "custom" extensions, which could apply default values directly, for example...

    public class MyCustomButtonBuilder extends ButtonBuilder<MyCustomButtonBuilder> {
        public MyCustomButtonBuilder(String text) {
            this(text, null);
        }
        
        public MyCustomButtonBuilder(Icon icon) {
            this(null, icon);
        }
        
        public MyCustomButtonBuilder(String text, Icon icon) {
            super();
            withText(text)
                    .withIcon(icon)
                    .borderPainted(false)
                    .focusPainted(false)
                    .contentAreaFilled(false);
        }
    }
    

    which could then be used something like...

    JButton sadButton = new MyCustomButtonBuilder("Sad", new ImageIcon(ImageIO.read(getClass().getResource("/images/Sad.png"))))
            .build();
    

    You could...

    Use a "factory pattern", for example...

    public class ButtonFactory {
        public static JButton makePlainButton() {
            return makePlainButton(null, null);
        }
    
        public static JButton makePlainButton(String text) {
            return makePlainButton(text, null);
        }
    
        public static JButton makePlainButton(String text, Icon icon) {
            JButton btn = new JButton(text, icon);
            btn.setBorderPainted(false);
            btn.setContentAreaFilled(false);
            btn.setFocusPainted(false);
            btn.setOpaque(false);
            return btn;
        }
    }
    

    which could be used something like...

    JButton heartButton = ButtonFactory.makePlainButton(
            "Heart", 
            new ImageIcon(ImageIO.read(getClass().getResource("/images/Heart.png")))
    );
    

    The factory pattern could allow you to supply a multiple number of different types of buttons, configured different based on your common needs.

    You could...

    Combine the two concepts, for example...

    public class ButtonFactory {
        public static JButton makePlainButton() {
            return makePlainButton(null, null);
        }
    
        public static JButton makePlainButton(String text) {
            return makePlainButton(text, null);
        }
    
        public static JButton makePlainButton(String text, Icon icon) {
            return new ButtonBuilder()
                    .withText(text)
                    .withIcon(icon)
                    .borderPainted(false)
                    .focusPainted(false)
                    .contentAreaFilled(false)
                    .build();
        }
    }