如何遍历JPanel的所有组件?

时间:2019-02-12 06:59:38

标签: java swing

我正在尝试使用JPanel遍历(循环)GridLayout(3,2)。对于其中的所有组件,如果它们是DescriptionPanel的实例,我想调用其getHours()方法。

问题

如何最好地“遍历” JPanel的所有组件?

我自己的尝试,不断抛出异常(请参见下文)

double hoursWorked = 0;
JPanel panel = new JPanel(new GridLayout(3,2));
.
.
.
for( int i = 0; i < panel.getComponentCount(); i++ ) {
    if(panel.getComponent(i) instanceof DescriptionPanel) {  //DescriptionPanel extends JPanel
        DescriptionPanel dp = (DescriptionPanel) panel.getComponent(i);
        hoursWorked += dp.getHours();
    }
}

我尝试将panel.getComponentCount()切换为实际号码(在这种情况下为6)。但是它总是抛出相同的错误消息。

for( int i = 0; i < 6; i++ ) {
    if(panel.getComponent(i) instanceof DescriptionPanel) {
        DescriptionPanel dp = (DescriptionPanel) panel.getComponent(i);
        hoursWorked += dp.getHours();
    }
 }

异常

  

线程“ AWT-EventQueue-0”中的异常   java.lang.ArrayIndexOutOfBoundsException:没有这样的孩子:2

2 个答案:

答案 0 :(得分:3)

这里最安全(并且我认为更优雅)的选项是使用面板的getComponents()方法并遍历组件。然后,对迭代器进行实例检查即可完成工作。

JPanel panel = new JPanel();
for (Component c : panel.getComponents()) {
    if (c instanceof DescriptionPanel)
    {
        DescriptionPanel dp = (DescriptionPanel) c;
        int hours = dp.getHours();
        // Do something with hours
    }
}

答案 1 :(得分:1)

也许我会将其发布为那些可能想知道为什么会发生这种情况的人的答案。

在AWT线程中修改了组件的布局,这很可能会更新容器中的某些内容,从而更改了组件的数量。

https://docs.oracle.com/javase/7/docs/api/java/awt/Container.html#getComponents()

文档指出,您应该使用Component.getTreeLock方法同步对这些方法的访问。 如:

    JPanel panel = new JPanel();
synchronized(panel.getTreeLock()) {
for (Component c : panel.getComponents()) {
    if (c instanceof DescriptionPanel)
    {
        DescriptionPanel dp = (DescriptionPanel) c;
        int hours = dp.getHours();
        // Do something with hours
    }
}
}