将字体传递给JPanel上的组件

4

我有一个扩展了JPanel类的类,上面有几个按钮。我想通过一次调用setFont(Font font)方法来设置所有按钮的字体。我在JPanel类中定义了setFont方法如下:

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);
            }
        }
    }
}

然而,按钮上的字体从未改变。我知道setFont被JPanel构造函数调用,但我不明白为什么当我在创建MyPanel对象之后明确调用它时,字体没有传递到按钮。

谢谢大家!

Brent


如果您需要更多帮助,请发布您的SSCCE(http://sscce.org)。 - camickr
4个回答

3

如果您希望应用程序中的所有后续按钮都使用不同的字体,您可以在实例化面板之前设置默认字体:

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

补充说明:更加专注的方法可能是在面板的构造函数中添加扩展JButton的实例:
buttons[i] = new MyButton(String.valueOf(i));
this.add(buttons[i]);

新按钮将始终具有相同的字体:
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);
    }
}

我喜欢这个。虽然它不完全是我正在寻找的解决方案,但这非常有帮助。非常感谢! - Brent Parker

2

不知道是否会更容易,但您也可以使用以下方法:

button.setFont(null);

对于每个按钮,都要执行相同的操作。当你想要改变字体时,可以执行以下操作:

panel.setFont(...);

按钮将继承面板的字体。我猜你需要在面板上调用repaint()方法。


我不知道!提前完成后,由于 setVisible() 的原因,repaint() 起作用了。 - trashgod
是的,如果在执行setVisible()之前构建GUI,则不需要做任何特殊处理。repaint()建议是为了在动态更改字体时使用。 - camickr
我首先构建GUI,最后一步是调用setVisible(true)。我认为可能是setVisible调用覆盖了我设置的字体。当我在setFont方法中添加“new Throwable().printStackTrace()”时,我看到三个堆栈跟踪。一个来自JPanel构造函数,然后一个来自我显式调用setFont,第三个堆栈与第一个构造函数调用完全相同。我认为,但不确定,它来自JPanel的初始绘制。 - Brent Parker

1

我相信在每个按钮上尝试使用“repaint”方法应该可以解决问题。


1
如果这是一个重绘问题,试着将GUI最小化并重新打开来查看是否解决。如果没有,你会发现有些东西在你之后设置按钮的字体。诊断这个问题的最好方法可能是创建一个JButton的子类(暂时),然后使用它来调试调用setFont() - 你可以检查堆栈跟踪以确定是谁在调用。
所以,
  1. 切换到一个按钮以简化代码:private JButton[] buttons = new JButton[10];
  2. buttons[i] = new JButton(""+i);更改为buttons[i] = new MyJButton(""+i);
  3. 创建MyJButton: class MyJButton extends JButton { @Override public void setFont(Font f) { super.setFont(f); // 在这一行上设置断点查看是谁在调用 } }
  4. 找到是否有更后面的setter之后,决定如何修复。你可以使用invokeLater(),或者更好的方法是找到一个逻辑点(构建后)来修改字体。
希望能帮到你。

我也在另一个答案中添加了这个评论,但我认为在这里也是合适的。我首先构建GUI,最后一件事是调用setVisible(true)。我实际上认为可能是setVisible调用覆盖了我设置的字体。当我在setFont方法中添加“new Throwable().printStackTrace()”时,我看到三个堆栈跟踪。一个来自JPanel构造函数,然后一个来自我显式调用setFont,第三个堆栈与第一个构造函数调用完全相同。我认为,但不确定,它来自JPanel的初始绘制。 - Brent Parker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接