Hello Guru's I am a beginner Java swing developer and am trying to build a simple app... here is a simplified version.
Setup: 1 JFrame, 2 BorderLayout based tabbed panels (A and B) each has 1 textfiled, shared JPanel class with combo box and ItemListener initialized in each tab's (North)
Issue: How to control updates to textfield's text based on which panel it came from eg. if I select Apples in TabA, the Item Listener updates the TextField on TabB as well. What I would like to accomplish is determine where the call came from TabA or TabB and only update the textfield associated with that tab.
Hope this makes some sense
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public JTextField tfPanelA;
public JTextField tfPanelB;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main frame = new Main();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
contentPane.add(tabbedPane, BorderLayout.CENTER);
JPanel panelA = new JPanel();
tabbedPane.addTab("Tab A", null, panelA, null);
panelA.setLayout(new BorderLayout(0, 0));
sharedPanel s1 = new sharedPanel(this);
panelA.add(s1, BorderLayout.NORTH);
tfPanelA = new JTextField();
panelA.add(tfPanelA);
tfPanelA.setColumns(10);
JPanel panelB = new JPanel();
tabbedPane.addTab("Tab B", null, panelB, null);
panelB.setLayout(new BorderLayout(0, 0));
sharedPanel s2 = new sharedPanel(this);
panelB.add(s2, BorderLayout.NORTH);
tfPanelB = new JTextField();
panelB.add(tfPanelB);
tfPanelB.setColumns(10);
}
}
// Shared Class...
public class sharedPanel extends JPanel {
private Main app;
private String[] clist = {"Apples","Oranges","Bananas"};
/**
* Create the panel.
*/
public sharedPanel(final Main app) {
this.app=app;
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setModel(new DefaultComboBoxModel<String>(clist));
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
//update PanelA's textfield ONLY if called from PanelA
// do this if called from PanelA
app.tfPanelA.setText(e.getItem().toString());
// do this if called from PanelB
app.tfPanelB.setText(e.getItem().toString());
}
});
add(comboBox);
}
}
Since you have create a new instance of sharedPanel
for each tab, simply provide a reference to the text field you want to be updated to it...
Which you end up with something more like...
public class sharedPanel extends JPanel {
private JTextField field;
private String[] clist = {"Apples","Oranges","Bananas"};
public sharedPanel(final JTextField field) {
this.field=field;
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setModel(new DefaultComboBoxModel<String>(clist));
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
sharedPanel.this.field.setText(e.getItem().toString());
}
});
add(comboBox);
}
}
Updated with a "model" example
This is very basic example of just one possible use of a model to bridge the changes between the common panel and other panels. This means that the common panel doesn't care about anything else and updates the supplied model, which fires events to interested parties who can take appropriate action as required.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TabbedModel {
protected static final String[] MAIN_LIST = {"Apples","Oranges","Bananas"};
public static void main(String[] args) {
new TabbedModel();
}
public TabbedModel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JTabbedPane tabPane = new JTabbedPane();
tabPane.addTab("A", new ATab());
tabPane.addTab("B", new ATab());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(tabPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DefaultCommonModel implements CommonModel {
private List<ChangeListener> listeners;
private String value;
public DefaultCommonModel() {
listeners = new ArrayList<>(25);
}
@Override
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
@Override
public void setValue(String aValue) {
if (aValue == null ? value != null : !aValue.equals(value)) {
value = aValue;
fireStateChanged();
}
}
@Override
public String getValue() {
return value;
}
protected void fireStateChanged() {
if (!listeners.isEmpty()) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
}
public interface CommonModel {
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
public void setValue(String value);
public String getValue();
}
public class CommonPanel extends JPanel {
private CommonModel model;
private JComboBox comboBox;
public CommonPanel(CommonModel model) {
this.model = model;
setLayout(new GridBagLayout());
comboBox = new JComboBox(new DefaultComboBoxModel<>(MAIN_LIST));
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
String value = (String) e.getItem();
CommonPanel.this.model.setValue(value);
}
});
add(comboBox);
}
}
public class ATab extends JPanel {
private List<JTextField> fields;
public ATab() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
DefaultCommonModel model = new DefaultCommonModel();
model.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
CommonModel model = (CommonModel) e.getSource();
for (JTextField field : fields) {
field.setText(model.getValue());
}
}
});
CommonPanel commonPanel = new CommonPanel(model);
add(commonPanel, gbc);
fields = new ArrayList<>(25);
for (int index = 0; index < random(); index++) {
JTextField field = new JTextField(10);
add(field, gbc);
fields.add(field);
}
}
protected int random() {
return (int)Math.round(Math.random() * 9) + 1;
}
}
}