views:

54

answers:

4

I have a class that extends JPanel with several buttons on it. I would like to be able to set the font on all the buttons with one call to setFont(Font font); I defined the setFont method in the JPanel class as such:

public class MyPanel extends JPanel {
    private JButton[] buttons = new JButton[10];

    public MyPanel() {
        for(int i = 0; i < 10; i++) {
            buttons[i] = new JButton(""+i);
            this.add(buttons[i]);
        }
    }

    public void setFont(Font font) {
        if(buttons != null) {
            for(JButton b : buttons) {
                b.setFont(font);
            }
        }
    }
}

However, the font on the button never changes. I understand that setFont is called by the JPanel constructor, but I don't understand why, when I call it clearly AFTER the MyPanel object is created, the fonts aren't passed on to the buttons.

Thanks everyone!

Brent

+1  A: 

I believe trying the "repaint" method on each of the buttons should work.

Mike
+1  A: 

If it is a repainting issue, minimize and re-open the gui to see if repaint fixes the problem. If not, you'll find that something is setting the font on the button after you are. Proabaly the best way to diagnose this is to create a subclass of JButton (temporarily) and use that to debug calls to setFont() - you'll be able to check the stack trace to see what is calling.

So,

  1. switch to one button to simplify: private JButton[] buttons = new JButton[10];
  2. change buttons[i] = new JButton(""+i); to buttons[i] = new MyJButton(""+i);
  3. create MyJButton: class MyJButton extends JButton { @override public void setFont(Font f) { super.setFont(f); // breakpoint this line and see who's calling } }
  4. Once you have found whether there's a later setter, decide how to fix. You could invokeLater() or better still find a logical point (Post construction) to alter the font.

Hope that helps

jowierun
I added this comment to another answer as well, but I thought it was appropriate here as well. -- I construct the gui first, and the last thing I do is call setVisible(true). I actually think it might be the setVisible call that is overriding the font I'm setting. When I add a "new Throwable().printStackTrace()" to the setFont method, I see three stack traces. One from the JPanel constructor, then one from when I explicitly call setFont, and a third with a stack that is EXACTLY like the first constructor call. I think, but am not sure, that it is from the initial drawing of the JPanel
Brent Parker
+2  A: 

If you want all subsequent buttons in the application to use a different font, you can set the default before instantiating the panel:

UIManager.put("Button.font", new FontUIResource("Dialog", Font.BOLD, 24));

Addendum: A more focused approach might be to add instances of an extended JButton in your panel's constructor:

buttons[i] = new MyButton(String.valueOf(i));
this.add(buttons[i]);

The new buttons would always have the same font:

private static class MyButton extends JButton {

    private static final Font font = new Font("Dialog", Font.BOLD, 24);

    public MyButton(String text) {
        super(text);
        this.setFont(font);
    }
}
trashgod
I like this. It's not exactly the solution I'm looking for, but this is very helpful. Thanks a lot!
Brent Parker
+1  A: 

Don't know if you will find it any easier but you can also use:

button.setFont(null);

for each of the buttons. Then when you want to change the font you can do:

panel.setFont(...);

and the buttons will inherit the font from the panel. I would guess you then need to invoke the repaint() method on the panel.

camickr
I didn't know that! Done early, the `repaint()` due to `setVisible()` works.
trashgod
Yes, if you build the GUI before doing the setVisible() you shouldn't have to do anything special. The repaint() suggestion was in case you dynamically needed to change the font.
camickr
I construct the gui first, and the last thing I do is call setVisible(true). I actually think it might be the setVisible call that is overriding the font I'm setting. When I add a "new Throwable().printStackTrace()" to the setFont method, I see three stack traces. One from the JPanel constructor, then one from when I explicitly call setFont, and a third with a stack that is EXACTLY like the first constructor call. I think, but am not sure, that it is from the initial drawing of the JPanel.
Brent Parker