Reputation: 147
I'm trying to traverse (loop through) a JPanel
, with GridLayout(3,2)
. And for all components in it, if they are an instance of DescriptionPanel
I want to call their getHours()
method.
Question,
How do I best 'loop through' all components of a JPanel
?
my own attempt, which keeps throwing an exception (see below)
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();
}
}
I have tried to switch panel.getComponentCount()
to its actualt number (6 in this case). But it keeps throwing the same error message.
for( int i = 0; i < 6; i++ ) {
if(panel.getComponent(i) instanceof DescriptionPanel) {
DescriptionPanel dp = (DescriptionPanel) panel.getComponent(i);
hoursWorked += dp.getHours();
}
}
Exception
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: No such child: 2
Upvotes: 1
Views: 1715
Reputation: 6818
The safest (and in my opinion more elegant) option here, is to use getComponents()
method of the panel and iterate through components. Then an instance check of the iterator will do the job.
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
}
}
Upvotes: 4
Reputation: 141
Maybe I will post it as an answer for those who might be wondering why this can occur.
The layout of the components is modified in AWT thread which is probably updating something in the container, thus changing the component's count.
https://docs.oracle.com/javase/7/docs/api/java/awt/Container.html#getComponents()
The documentation states that you should synchronize the access to these methods using the Component.getTreeLock
method.
Such as:
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
}
}
}
Upvotes: 1