Using a JTabbedPane, I'd like to capture the moment just immediately before the change in the selection of a new tab is effective and perform an action. It'd be something analogous to a focus-lost event for a swing component. The aim is to save the text of a few JTextFields into an external file when the tab is changed, so everytime the user clicks a different tab, the values of the current tab are written into the external file.
I've been using the ChangeListener to track the change of tabs, but haven't found a way to do what I need. Any ideas in how to achieve it in the next simple example?
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TabSample {
static void add(JTabbedPane tabbedPane, String label) {
JButton button = new JButton(label);
tabbedPane.addTab(label, button);
}
public static void main(String args[]) {
JFrame frame = new JFrame("TabSample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTabbedPane tabbedPane = new JTabbedPane();
String titles[] = { "Geometry", "Materials", "Analysis"};
for (int i = 0, n = titles.length; i < n; i++) {
add(tabbedPane, titles[i]);
}
ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
JTabbedPane sourceTabbedPane = (JTabbedPane) changeEvent.getSource();
int index = sourceTabbedPane.getSelectedIndex();
System.out.println("Tab changed to: " + sourceTabbedPane.getTitleAt(index));
}
};
tabbedPane.addChangeListener(changeListener);
frame.add(tabbedPane, BorderLayout.CENTER);
frame.setSize(400, 150);
frame.setVisible(true);
}
}
One possible way, and I'm not 100% sure that this is acceptable to do or not, but is to create your own model for the JTabbedPane, a model which implements SingleSelectionModel (check the SingleSelectionModel API), that overrides the
setSelectedIndex(int index)
method, the method that I'm pretty sure Swing uses when it wants to tell the JTabbedPane to change tabs. If you create a class that extends from the DefaultSingleSelectionModel, a concrete class that implements the above interface and override this method, you could make method calls before the super's method is called, and thus make GUI calls before the tab changes. For example, yoursetSelectedIndex
method could look like this:And using your code above could be implemented like:
Note that I use a boolean field,
activated
to activate the behavior change so that it doesn't fire on GUI creation. I callsetActivated(true)
on the model after displaying the GUI.Regarding your edit:
I should have known, it was an XY Problem after all, where you ask how to solve a specific code problem when the best solution is to use a completely different approach. In the future, please give us all pertinent information with the original question so we can avoid wasting time with unnecessary solutions.
There is in fact no need here to do anything before the tab changes since it is perfectly fine to get the data when the tabs change. Your solution is to use a ChangeListener, and there's no need to go through the gymnastics of what I posted above.