I gotta say, java swing isn't the greatest framework for creating interfaces with objects that need to be updated depending on selections. I came across this issue when I trying to create a panel that would dynamically allocate objects depending on the class that this panel was inheriting by the users choice from a radio button selection. When a panel was created with the allocated objects, the containing panel would not recognize those changes even after repainting and revalidating. The trick is knowing how the event driven swing framework works. Since the objects were not originally created by the event dispatch thread a.k.a. AWT-EventQueue, they will not take effect until an EventQueue owned object "affects" it. So how would the EventQueue thread "own" the interface objects that were not created in the first place?
In comes the SwingWorker. This is an abstract class that allows dynamic background processes to update the object being modified even if the process is a concurrent running process. The SwingWorker can publish the object at any time even in the middle of a process since it publishes itself to the even dispatch thread which will then take ownership of the object in need of updating. Now loading bars and live dynamic object allocation are possible. I've created a class below that extends the SwingWorker class, but it can take any Swing parent component (the one that contains the object needed to be modified) and a method associated with a child Swing component. Depending on what the child method does, this will update the interface of the parent that will be containing the childs actions.
For example, I have a Jpanel that contains another Jpanel that will update some JComboBoxes with different values. The kicker is that depending on the child class, there can different quantities of JComboBoxes.
Sample Code:
public class DocTypeContainPanel extends JPanel{
...
SwingObjectWorker temp1 = null;
SwingObjectWorker temp2 = null;
temp1 = new SwingObjectWorker(pnlSearchPropsContainer, pnlSearchProps.getPropsPanel());
temp1.execute();
temp2 = new SwingObjectWorker(pnlDocPropsContainer, pnlDocProps.getPropsPanel());
temp2.execute();
revalidate();
repaint();
...
}
class SwingObjectWorker extends SwingWorker<JComponent, Void> {
private JComponent parentComp;
private JComponent childComp;
public SwingObjectWorker (JComponent inparentComp, JComponent inchildComp){
parentComp = inparentComp;
childComp = inchildComp;
final SwingObjectWorker temp = this;
this.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent arg0) {
if (StateValue.DONE == temp.getState()) {
try {
parentComp.removeAll();
parentComp.add(get(), "cell 0 0,grow");
parentComp.setVisible(true);
parentComp.revalidate();
parentComp.repaint();
System.out.println("Swing Worker Done!");
// TODO: insert code to run on the EDT after move determined
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
});
}
@Override
public JComponent doInBackground() {
return childComp;
}
@Override
public void done() {
}
}
No comments:
Post a Comment