I am trying to build an MVC application in Java Swing. I have a JPanel that contains four JComboBoxes and this JPanel is embedded into a parent JPanel. The parent JPanel has other controls in addition to the child JPanel.
The child JPanel's model gets correctly updated whenever I change the values of the JComboBoxes (it's basically a date picker with one combo box each for year, month, day of month, and hour of day). What I cannot figure out is how I can trigger the parent JPanel's model to update itself to match the value stored in the child JPanel's model whenever one of the JComboBoxes is changed.
Below is a stripped down SSCCE of the structure of what I have so far. Thank you.
import java.awt.event.*;
import javax.swing.*;
public class Example extends JFrame {
public Example() {
super();
OuterView theGUI = new OuterView();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
add(theGUI);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Example();
}
});
}
}
class OuterView extends JPanel {
public OuterView() {
super();
InnerView innerPanel = new InnerView();
JButton button = new JButton("display OuterView's model");
button.addActionListener(new ButtonListener());
add(innerPanel);
add(button);
}
private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("button was clicked");
}
}
}
class InnerView extends JPanel {
public InnerView() {
super();
String[] items = new String[] {"item 1", "item 2", "item 3"};
JComboBox comboBox = new JComboBox(items);
comboBox.addActionListener(new ComboBoxListener());
add(comboBox);
}
private class ComboBoxListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
String text = ((JComboBox) ae.getSource()).getSelectedItem().toString();
System.out.println("store " + text + " in InnerView's model");
System.out.println("now how do I cause OuterView's model to be updated to get the info from InnerView's model?");
}
}
}
First off as @Sage mention in his comment a JPanel is rather a container than a component which do action. So you can't attach an ActionListener to a JPanel .
Adding components to JPanel To add GUI components such as JLabel, JTextField, JButton... to the panel, we use the add() method. There are different versions of the add() method, so which method to be used is depending on the layout manager of the panel.
getContentPane(). add(scrollPanel); This code will work in general to add JScrollPane to JPanel. Adjust bounds of frame, panel and scrollpane according to your requirements but ensure that the bounds of JScrollPane are within the bounds of the frame otherwise the scrollpane will not be visible.
JPanel is a subclass of the JComponent, which is a child of the Container; therefore, JPanel is also considered a container. There are many methods used by JPanel, which it inherits from its parent classes.
You could use a PropertyChangeListener, and in fact one is built into every component. e.g.:
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class Example extends JFrame {
public Example() {
super();
OuterView theGUI = new OuterView();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
add(theGUI);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Example();
}
});
}
}
class OuterView extends JPanel {
private String innerValue = "";
public OuterView() {
super();
InnerView innerPanel = new InnerView();
innerPanel.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(InnerView.COMBO_CHANGED)) {
innerValue = evt.getNewValue().toString();
System.out.println("new value from inside of OuterView: "
+ innerValue);
}
}
});
JButton button = new JButton("display OuterView's model");
button.addActionListener(new ButtonListener());
add(innerPanel);
add(button);
}
private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("button was clicked. innerValue: " + innerValue);
}
}
}
class InnerView extends JPanel {
public static final String COMBO_CHANGED = "Combo Changed";
// private SwingPropertyChangeSupport pcSupport = new
// SwingPropertyChangeSupport(this);
String oldValue = "";
public InnerView() {
super();
String[] items = new String[] { "item 1", "item 2", "item 3" };
JComboBox comboBox = new JComboBox(items);
comboBox.addActionListener(new ComboBoxListener());
add(comboBox);
}
private class ComboBoxListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ae) {
String text = ((JComboBox) ae.getSource()).getSelectedItem()
.toString();
firePropertyChange(COMBO_CHANGED, oldValue, text);
oldValue = text;
System.out.println("store " + text + " in InnerView's model");
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With