I'm using the javax.swing library, and I try to solve this problem:
I have a MenuBar in which I created JMenu, this menu has JCheckBoxMenuItem items. Like this:
//creating objects:
jMenuBar = new javax.swing.JMenuBar();
jMenuAlgorithms = new javax.swing.JMenu();
jCheckBoxSPEA = new javax.swing.JCheckBoxMenuItem();
jCheckBoxNSGAII = new javax.swing.JCheckBoxMenuItem();
jSeparator1 = new javax.swing.JPopupMenu.Separator();
jCheckBoxMenuEnableAll = new javax.swing.JCheckBoxMenuItem();
jCheckBoxMenuDisableAll = new javax.swing.JCheckBoxMenuItem();
//settings and putting them together:
jCheckBoxSPEA.setSelected(true);
jCheckBoxSPEA.setText("SPEA");
jMenuAlgorithms.add(jCheckBoxSPEA);
jCheckBoxNSGAII.setSelected(true);
jCheckBoxNSGAII.setText("NSGAII");
jMenuAlgorithms.add(jCheckBoxNSGAII);
jMenuAlgorithms.add(jSeparator1);
jCheckBoxMenuEnableAll.setSelected(true);
jCheckBoxMenuEnableAll.setText("Enable all");
jCheckBoxMenuEnableAll.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jCheckBoxMenuEnableAllMouseClicked(evt);
}
});
jMenuAlgorithms.add(jCheckBoxMenuEnableAll);
jCheckBoxMenuDisableAll.setText("Disable all");
jMenuAlgorithms.add(jCheckBoxMenuDisableAll);
jMenuBar.add(jMenuAlgorithms);
If the user selects jCheckBoxMenuEnableAll item, I would like to select all the items above the separator. If he selects jCheckBoxMenuDisableAll, I would like to deselect all the items above the separator.
As you can see, I've added mouseClicked action to the jCheckBoxMenuEnableAll item. Now, I would like to do something like this:
private void jCheckBoxMenuEnableAllMouseClicked(java.awt.event.MouseEvent evt) {
for(JCheckBoxMenuItem item : jMenuAlgorithms){
item.setSelected(true);
}
//deselect then jCheckBoxMenuDisableAll, it's not essential for instance
}
But apparently, I can't do the for loop like this, as the menu item isn't an array or Iterable.
Well, just for testing, I had done something very stupid (code below) - I pass all the items in the menu, and if the item is a check box, I make its copy, set ist value to "true" (selected) and then replace the original item by its copy. Very stupid, I know and I absolutely don't want to do like this, however, I didn't find another way to do it. I just wanted to see if this would work. I supposed it should, but it stoll doesn't work. What am I doing wrong? Thank you very, very much for your time.
private void jCheckBoxMenuEnableAllMouseClicked(java.awt.event.MouseEvent evt) {
if(jCheckBoxMenuEnableAll.isSelected()){
for(int i =0; i< jMenuAlgorithms.getItemCount(); i++){ //for all items in the menu, separators included
if(jMenuAlgorithms.getItem(i) instanceof JCheckBoxMenuItem){
JCheckBoxMenuItem item = ((JCheckBoxMenuItem)jMenuAlgorithms.getItem(i));
item.setSelected(true);
jMenuAlgorithms.insert(item, i);
}
}
}
}
I think JPopupMenu#getSubElements() is what you are looking for.
see also: JMenu#getSubElements()
Returns an array of MenuElements containing the submenu for this menu
component. If popup menu is null returns an empty array. This method
is required to conform to the MenuElement interface. Note that since
JSeparators do not conform to the MenuElement interface, this array
will only contain JMenuItems.
import java.awt.*;
import java.util.Arrays;
import java.util.stream.Stream;
import javax.swing.*;
public class MenuSubElementsTest {
public JComponent makeUI() {
JMenu jMenuAlgorithms = new JMenu("MenuAlgorithms");
JMenuItem jCheckBoxMenuEnableAll = new JMenuItem("Enable all");
jCheckBoxMenuEnableAll.addActionListener(e -> {
for (MenuElement me: jMenuAlgorithms.getPopupMenu().getSubElements()) {
System.out.println("debug1: " + me.getClass().getName());
if (me instanceof JCheckBoxMenuItem) {
((JCheckBoxMenuItem) me).setSelected(true);
}
}
//or: getJCheckBoxMenuItem(jMenuAlgorithms).forEach(r -> r.setSelected(true));
});
JMenuItem jCheckBoxMenuDisableAll = new JMenuItem("Disable all");
jCheckBoxMenuDisableAll.addActionListener(e -> {
getJCheckBoxMenuItem(jMenuAlgorithms).forEach(r -> r.setSelected(false));
});
jMenuAlgorithms.add(new JCheckBoxMenuItem("SPEA", true));
jMenuAlgorithms.add(new JCheckBoxMenuItem("NSGAII", true));
jMenuAlgorithms.addSeparator();
jMenuAlgorithms.add(jCheckBoxMenuEnableAll);
jMenuAlgorithms.add(jCheckBoxMenuDisableAll);
JMenuBar jMenuBar = new JMenuBar();
jMenuBar.add(jMenuAlgorithms);
JPanel p = new JPanel(new BorderLayout());
p.add(jMenuBar, BorderLayout.NORTH);
return p;
}
private static Stream<JCheckBoxMenuItem> getJCheckBoxMenuItem(MenuElement p) {
Class<JCheckBoxMenuItem> clz = JCheckBoxMenuItem.class;
return stream(p).filter(clz::isInstance).map(clz::cast);
}
// public static Stream<MenuElement> stream(MenuElement p) {
// return Arrays.stream(p.getSubElements())
// .map(MenuSubElementsTest::stream).reduce(Stream.of(p), Stream::concat);
// }
public static Stream<MenuElement> stream(MenuElement p) {
return Stream.concat(Stream.of(p), Arrays.stream(p.getSubElements())
.peek(me -> System.out.println("debug2: " + me.getClass().getName()))
.flatMap(MenuSubElementsTest::stream));
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new MenuSubElementsTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
Related
I'm trying to learn the difference between Hashtable and HashMap and I'm trying to add specific prices to these items here. The goal is to print the price of the item selected from comboItem into txtPrice.
String[] items = {"Select Item","Betta Fish","Snail","Supplies","Food"};
comboGroup = new JComboBox<String>(items);
comboGroup.addActionListener(this);
comboGroup.setBounds(130,35,150,40);
comboItem = new JComboBox<>();
comboItem.setPrototypeDisplayValue("XXXXXXXXXXX");
comboItem.setBounds(130,85,150,40);
String[] subItems1 = {"Select Betta","Plakat","Halfmoon","Double Tail","Crown Tail"};
subItems.put(items[1], subItems1);
String[] subItems2 = {"Select Snail","Pond Snail","Ramshorn","Apple Snail","Assassin Snail"};
subItems.put(items[2], subItems2);
String[] subItems3 = {"Select Supply","Small Fine Net","Large Fine Net","Flaring Mirror","Aquarium Hose (1meter)"};
subItems.put(items[3], subItems3);
String[] subItems4 = {"Select Food","Daphnia","Tubifex","Mosquito Larvae","Optimum Pellets"};
subItems.put(items[4], subItems4);
comboGroup.setSelectedIndex(1);
//TextFields <- this is the attempt to add price to subItems value but commented out
/*int[] items1price = {0,150,350,200,200};
subItems.put(items[1], items1price);
int[] items2price = {0,15,25,80,120};
subItems.put(items[2], items2price);
int[] items3price = {0,50,80,25,15};
subItems.put(items[3], items3price);
int[] items4price = {0,50,100,50,50};
subItems.put(items[4], items4price);
comboGroup.setSelectedIndex(1);
*/
txtPrice = new JTextField();
txtPrice.setBounds(130,135,150,40);
So far with my understanding from HashMap applying it to CLi and not in GUI, If I try HashMap<String,Integer> I can only print it altogether in a single line.
eg.
HashMap<String,Integer> item = new HashMap<String,Integer>();
item.put("Plakat",50);
CLi Prints:
Plakat=50
What I want is to print Plakat from selected comboItem then print 50 to txtPrice but I don't know how to do that.
The whole code is here: https://github.com/kontext66/GuwiPos
GUI and Main.
Additional note: I am a beginner and I'm trying to understand Layout Manager for now, so the code here is a bit messy and literal.
Below is an example using JComboBox and HashMap to get the corresponding "prices" to specific items in the combo box. I would suggest going through the tutorial on How to Use Various Layout Managers and choose the ones that suit you best. As for the difference between HashMap and HashTable, please have a look at this answer. The main difference is that HashTable is synchronized, whereas HashMap is not, and since synchronization is not an issue for you, I'd suggest HashMap. Also, another option would be to add instances of a custom object to a JComboBox, as described here. Thus, there would be no need to use HashMap.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class App {
Map<String, String> map;
JTextField tf;
public App() {
map = new HashMap<String, String>();
map.put("Plakat", "50");
map.put("Halfmoon", "25");
map.put("Double Tail", "80");
}
private void addComponentsToPane(Container pane) {
String[] items = { "Select Item", "Plakat", "Halfmoon", "Double Tail" };
JComboBox<String> comboBox = new JComboBox<String>(items);
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.SELECTED) {
String item = (String) event.getItem();
System.out.println(item);
tf.setText(map.get(item));
}
}
});
tf = new JTextField();
JPanel p = new JPanel();
pane.add(comboBox, BorderLayout.NORTH);
pane.add(tf, BorderLayout.SOUTH);
}
private void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addComponentsToPane(frame.getContentPane());
// frame.setSize(640, 480);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new App().createAndShowGUI();
}
});
}
}
Update
Below is the implementation of the second approach described earlier, where a custom object is used for adding items to a JComboBox, and hence, there is no need to use a HashMap.
P.S. I should also add that if the user shouldn't be allowed to edit the "price" in the text field, then you should use tf.setEditable(false);, or even use a JLabel instead.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class App {
JTextField tf;
class ComboItem {
private String key;
private String value;
public ComboItem(String key, String value) {
this.key = key;
this.value = value;
}
#Override
public String toString() {
return key;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
}
private void addComponentsToPane(Container pane) {
JComboBox<ComboItem> comboBox = new JComboBox<ComboItem>();
comboBox.addItem(new ComboItem("Select Item", ""));
comboBox.addItem(new ComboItem("Plakat", "50"));
comboBox.addItem(new ComboItem("Halfmoon", "25"));
comboBox.addItem(new ComboItem("Double Tail", "80"));
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.SELECTED) {
Object item = comboBox.getSelectedItem();
String value = ((ComboItem) item).getValue();
tf.setText(value);
}
}
});
tf = new JTextField();
JPanel p = new JPanel();
pane.add(comboBox, BorderLayout.NORTH);
pane.add(tf, BorderLayout.SOUTH);
}
private void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addComponentsToPane(frame.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new App().createAndShowGUI();
}
});
}
}
Update 2
To convert the string from the text field into double, you can use Double.parseDouble(String), as shown below (again, make sure to use tf.setEditable(false);, so that the value cannot be modified by the user).
double price = 0;
if (tf.getText() != null && !tf.getText().trim().isEmpty())
price = Double.parseDouble(tf.getText());
System.out.println(price);
consider the following code:
mntmProfilesDelete.get(index).addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
JMenuItem eMntm = (JMenuItem) e.getSource();
String text = eMntm.getText();
Component[] mns = mnDelete.getParent().getComponents();
for(Component mn : mns)
{
System.err.println((String)(((JMenu)mn).getText()));
if(mn instanceof JMenu && ((JMenu)mn).getText().toLowerCase().equals("open"))
{
System.err.println((String)(((JMenu)mn).getText()));
Component[] mntms = ((JMenu) mn).getComponents();
for(Component mntm : mntms)
{
System.err.println((String)(((JMenu)mn).getText())+"\n"+(String)(((JMenuItem)mntm).getText()));
if(mntm instanceof JMenuItem && ((JMenuItem)mntm).getText().toLowerCase().equals(text.toLowerCase()))
{
System.err.println((String)(((JMenu)mn).getText())+"\n"+(String)(((JMenuItem)mntm).getText()));
((JMenu)mn).remove((JMenuItem)mntm);
}
}
}
}
mnDelete.remove(eMntm);
}
}
which I'm using to delete two menu items, like below:
(jmenu)father
(jmenu)open
(jmenuitem)item1
(jmenuitem)item2
etc
(jmenu)delete
(jmenuitem)item1
(jmenuitem)item2
etc
the action listener is attached to -item1- below -delete-
for some reason the -item1- below -open- doesn't get removed using the above code. I can't seem to understand why.
many thanks.
JMenu's remove(Component c) JavaDoc says: "Removes the component c from this menu."
AFAIC interpret from looking at the last line of your code (my weekend mind refused to dig through the casting galore[1] ;-) and your explanation: your this menu mnDelete is /father/delete. The item you're trying to remove (/father/open/item1) is not in this menu.
[1] Why the heck are you casting public String getText() to (String)?
So I would save off my menu that I want to modify so I can easily perform this change. As opposed to trying to wind through the hierarchy. This will make it much easier to read your code. For example:
public SomeApp {
JMenu openMenu;
JMenu deleteMenu;
public JMenu buildMenus(List<SomeObject> objsThatGoInMenu) {
openMenu = new JMenu("Open");
deleteMenu = new JMenu("Delete");
for( SomeObject so : objsThatGoInMenu ) {
addMenuOptions( so );
}
JMenu father = new JMenu("Father");
father.add( openMenu );
father.add( deleteMenu );
}
public addMenuOptions( final SomeObject so ) {
final JMenuItem openMenuItem = new JMenuItem( new AbstractAction( so.getName() ) {
public void actionPerformed(ActionEvent evt) {
// todo open
}
}));
final JMenuItem deleteMenuItem = new JMenuItem( new AbstractAction( so.getName() ) {
public void actionPerformed(ActionEvent evt) {
deleteMenu.remove( deleteMenuItem );
openMenu.remove( openMenuItem );
}
}));
openMenu.add( openMenuItem );
deleteMenu.add( deleteMenuItem );
}
}
solved it, every part of my code works as it should except:
Component[] mntms = ((JMenu) mn).getComponents();
which does not return any JMenuItems, it should be:
Component[] mntms = ((JMenu) mn).getMenuComponents();
My menuitem are being added thorugh database .
i have to perform action such as opening the new jframe , if a user select a particular menuitem.
Here the menu dimension is add to the Menubar , and under which various menuitem are being added such as Period , Entity, which are being fetch from database.
Now i want to open a new jframe on the click of Period menuitem .
public void MenuExp(){
JMenu DimensionMenu = new JMenu("Dimension");
JMenu editMenu = new JMenu("Help");
jMenuBar1.add(DimensionMenu);
jMenuBar1.add(editMenu);
//JMenuItem newAction = new JMenuItem("Account");
//fileMenu.add(newAction);
//JMenuItem newPeriod = new JMenuItem("Period");
//fileMenu.add(newPeriod);
try{
Class.forName("oracle.jdbc.OracleDriver");
Connection comm = (Connection)DriverManager.getConnection("jdbc:oracle:thin:#192.168.100.25:1521:orcl","SYSTEM","Admin123");
Statement st = comm.createStatement();
String Query = "select OBJECT_NAME from RAHUL_APP1.HSP_OBJECT where OBJECT_TYPE = 2 AND OBJECT_ID <> 30" ;
//and User_Name ='" + jTextField1.getText()+"'";
ResultSet rs = st.executeQuery(Query);
while(rs.next()){
JMenuItem newAction = new JMenuItem(rs.getString(1));
DimensionMenu.add(newAction);
rs.close();
st.close();
comm.close();
newAction.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0){
System.out.println("You have clicked on the Account");
}
});
}
} catch(Exception e){
JOptionPane.showMessageDialog(this,e);
}
}
You need to do some parametrization of the frame or have for example frame class stored also in DB and initialize it using reflexion...
Update:
Implementation can be like this:
package betlista.so.swing.menuitemdialogsfromdb;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class MainFrame extends JFrame {
public MainFrame() {
super("Frame");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
add(createMenu());
pack();
}
private JMenuBar createMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Open");
menu.add(new DialogCreatingMenuItem("Dialog 1", "betlista.so.swing.menuitemdialogsfromdb.MainFrame$MyDialog1"));
menu.add(new DialogCreatingMenuItem("Dialog 2", "betlista.so.swing.menuitemdialogsfromdb.MainFrame$MyDialog2"));
menuBar.add(menu);
return menuBar;
}
class DialogCreatingMenuItem extends JMenuItem implements ActionListener {
String className;
public DialogCreatingMenuItem(String text, String className) throws HeadlessException {
super(text);
this.className = className;
addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent ae) {
try {
Class<JDialog> clazz = (Class<JDialog>)Class.forName(this.className);
JDialog dialog = clazz.newInstance();
dialog.setVisible(true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
public static class MyDialog1 extends JDialog {
public MyDialog1() {
setTitle("Dialog 1");
add(new JLabel("Dialog 1"));
pack();
}
}
public static class MyDialog2 extends JDialog {
public MyDialog2() {
setTitle("Dialog 2");
add(new JLabel("Dialog 2"));
pack();
}
}
public static void main(String[] args) {
new MainFrame().setVisible(true);
}
}
where Strings in
menu.add(new DialogCreatingMenuItem("Dialog 1", "betlista.so.swing.menuitemdialogsfromdb.MainFrame$MyDialog1"));
menu.add(new DialogCreatingMenuItem("Dialog 2", "betlista.so.swing.menuitemdialogsfromdb.MainFrame$MyDialog2"));
are retrieved from database...
Here is a sample code:
menuItem1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
...
}
});
Remember the steps to creating a menu:
1. Create a MenuBar and add to the panel
2. Create a Menu and add to MenuBar
3. Create a MenuItem and add to Menu
Then add the listener to the MenuItem
Edit: if you use it outside the try statement it should work
Now i want to open a new jframe on the click of Period menuitem
Of course you have to add an ActionListener to your menu to do that, but the real question is How do you determine the right listener to each menu item? Since you fetch your menu items from database then it's not that easy as it looks like.
Note: see The Use of Multiple JFrames, Good/Bad Practice?
Option 1 (kind of dirty)
As I've said, you could store an action command and set it back to the menu item just like you set the menu's name:
while(rs.next()) {
String menuName = rs.getString("menuname");
String actionCommand = rs.getString("actioncommand");
JMenuItem newAction = new JMenuItem(menuName);
newAction.setActionCommand(actionCommand);
DimensionMenu.add(newAction);
...
}
Then you can have a listener that make use of ActionEvent#getActionCommand() to decide the right action to perform and attach this listener to all your menu items:
class MenuActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent evt) {
String actionCommand = evt.getActionCommand();
switch (actionCommand) {
case "OpenNewDialog": openNewDialog(); break;
...
}
}
private void openNewDialog() {
// implementation here
}
}
Then:
ActionListener listener = new MenuActionListener();
while(rs.next()) {
String menuName = rs.getString("menuname");
String actionCommand = rs.getString("actioncommand");
JMenuItem newAction = new JMenuItem(menuName);
newAction.setActionCommand(actionCommand);
newAction.addActionListener(listener);
DimensionMenu.add(newAction);
...
}
Option 2
Implement Factory method pattern to create a specific ActionListener or Action based on menu's action command:
class ActionListenerFactory {
public static Action createAction(final String actionCommand) {
switch (actionCommand) {
case "OpenNewDialog": return openNewDialogAction(); break;
...
}
}
private Action openNewDialogAction() {
Action action = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent evt) {
// open new dialog here
}
};
return action;
}
}
Then:
while(rs.next()) {
String menuName = rs.getString("menuname");
String actionCommand = rs.getString("actioncommand");
JMenuItem newAction = new JMenuItem(menuName);
newAction.setActionCommand(actionCommand);
newAction.addActionListener(ActionListenerFactory.createAction(actionCommand));
DimensionMenu.add(newAction);
...
}
See also:
How to Use Actions tutorial.
Concurrency in Swing lesson.
Worker threads and SwingWorker to do database calls in a background thread and create/update Swing component in the Event Dispatch Thread
I'm creating a program that reads data from a file, displays it on a GUI that has a JList and JButtons. I am trying to write it with CardLayout so the appropriate JPanel can be displayed when an item is selected from the JList or a JButton is clicked (i.e. next, previous, first and last). I am able to successfully read from the file and display data to the GUI. I've run into 2 problems and I've tried searching online for answers but cant seem to figure it out:
1) How do I get the JPanels to switch using CardLayout?
2) How do I get the data to be displayed in the GUI in text fields when a user clicks an item from the JList? The JList does appear and my ListSelectionListener is working because when I click on a particular item, it will print to the console (as a test).
If I comment out all of the JPanels except for 1, then it is correctly displayed but when I place all of them, then it does not switch.
So far, I have this for my ListSelectionListener (as an inner class):
public class CancerSelectionListener implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
Integer selection = (Integer)(((JList) e.getSource()).getSelectedIndex());
if(selection == 0) {
System.out.println("blah"); // works
// switch to the corresponding JPanel in CardLayout
}
}
}
String[] tester;
String teste;
listModel = new DefaultListModel();
for(int i = 0; i < 36; i++) {
tester = _controller.readCancer(i); // reads from the file, this part works!
teste = tester[0];
listModel.addElement(teste);
}
cancerList = new JList(listModel);
cancerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cancerList.setSelectedIndex(-1);
cancerList.setVisibleRowCount(5);
cancerListScroller = new JScrollPane(cancerList);
CardLayout myCardLayout;
myCardLayout = new CardLayout();
mainPanel2.setLayout(myCardLayout);
myCardLayout.show(mainPanel2, "test");
CancerPanels.aplPanel apl = new CancerPanels.aplPanel();
CancerPanels.fcPanels fc = new CancerPanels.fcPanels();
CancerPanels.vhlsPanels vhls = new CancerPanels.vhlsPanels();
CancerPanels.pdgPanels pdg = new CancerPanels.pdgPanels();
CancerPanels.cebpaPanels cebpa = new CancerPanels.cebpaPanels();
mainPanel2.add(apl.aplReturn(), "test");
mainPanel2.add(fc.fcReturn());
mainPanel2.add(vhls.vhlsReturn());
mainPanel2.add(pdg.pdgReturn());
mainPanel2.add(cebpa.cebpaReturn());
// I have 37 JPanels that are placed in the JPanel that uses CardLayout but I didn't post all of them as it would take up lots of space
The data for each JPanel is populated from static inner classes in the CancerPanels class (only showing 1 as each is very long!)
public class CancerPanels extends CancerGUI {
static JPanel cards;
static CancerController _cons = new CancerController();
static String[] cancerData;
static JScrollPane treatmentsScroller = new JScrollPane(txtTreatments, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane causesScroller = new JScrollPane(txtCauses, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane symptomsScroller = new JScrollPane(txtSymptoms, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
public static class aplPanel extends JPanel {
public JPanel aplReturn() {
treatmentsScroller.setViewportView(txtTreatments);
txtTreatments.setEditable(false);
causesScroller.setViewportView(txtCauses);
txtCauses.setEditable(false);
symptomsScroller.setViewportView(txtSymptoms);
txtSymptoms.setEditable(false);
cards = new JPanel(new GridLayout(6,1));
cancerData = _cons.readCancer(0);
resultName.setText(cancerData[0]);
txtSymptoms.setText(cancerData[1]);
txtCauses.setText(cancerData[2]);
txtTreatments.setText(cancerData[3]);
resultRate.setText(cancerData[4]);
resultPrognosis.setText(cancerData[5]);
cards.add(resultName);
cards.add(symptomsScroller);
cards.add(causesScroller);
cards.add(treatmentsScroller);
cards.add(resultRate);
cards.add(resultPrognosis);
return cards;
}
}
Edit:
Here is my most recent attempt. I can scroll through the JList but it doesn't properly display the correct corresponding JPanel (in fact it doesn't display anything, except whenever I click the last button, I don't know why that button works). I successfully managed to place an ItemListener on a JComboBox but ultimately, I want the CardLayout to work. Our instructor provided us with sample code to use but when I try it, the JPanels do not switch (or if they do they're hidden, not sure why).
Each of my listeners are public inner classes in the overall CancerGUI class.
public CancerGUI() {
CancerPanels.aplPanel apl = new CancerPanels.aplPanel();
CancerPanels.fcPanels fc = new CancerPanels.fcPanels();
CancerPanels.vhlsPanels vhls = new CancerPanels.vhlsPanels();
// more than 30 JPanels that I add to the JPanel that uses CardLayout, so I only posted 3
// each of them uses the GridLayout
mainPanel2 = new JPanel(new CardLayout());
mainPanel2.add(apl.aplReturn(), "1");
mainPanel2.add(fc.fcReturn(), "2");
mainPanel2.add(vhls.vhlsReturn(), "3");
CancerActionButtons _cab = new CancerActionButtons();
btnNext = new JButton("Next");
btnPrevious = new JButton("Previous");
btnFirst = new JButton("First");
btnLast = new JButton("Last");
btnClear = new JButton("Clear");
btnNext.addActionListener(_cab);
btnPrevious.addActionListener(_cab);
btnFirst.addActionListener(_cab);
btnLast.addActionListener(_cab);
CancerItemListener _item = new CancerItemListener(); // this listener works!
renalC.addItemListener(_item);
skinC.addItemListener(_item);
brainC.addItemListener(_item);
bladderC.addItemListener(_item);
ovarianC.addItemListener(_item);
pancC.addItemListener(_item);
breastC.addItemListener(_item);
String[] tester;
String teste;
listModel = new DefaultListModel();
for(int i = 0; i < 36; i++) {
tester = _controller.readCancer(i);
teste = tester[0];
listModel.addElement(teste);
}
cancerList = new JList(listModel);
cancerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
cancerList.setSelectedIndex(-1);
cancerList.setVisibleRowCount(5);
cancerListScroller = new JScrollPane(cancerList);
ListSelection _list = new ListSelection();
cancerList.addListSelectionListener(_list);
JScrollPane treatmentsScroller = new JScrollPane(txtTreatments, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
treatmentsScroller.setViewportView(txtTreatments);
JScrollPane causesScroller = new JScrollPane(txtCauses, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
causesScroller.setViewportView(txtCauses);
JScrollPane symptomsScroller = new JScrollPane(txtSymptoms, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
symptomsScroller.setViewportView(txtSymptoms);
public class ListSelection implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
String selection = (String)(((JList)e.getSource()).getSelectedValue());
((CardLayout) mainPanel2.getLayout()).show(mainPanel2, selection);
((CardLayout) mainPanel2.getLayout()).show(mainPanel2, selection);
}
}
public class CancerActionButtons implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
switch(e.getActionCommand()) {
case "First":
((CardLayout) mainPanel2.getLayout()).first(mainPanel2);
cancerCount = 1;
break;
case "Last":
((CardLayout) mainPanel2.getLayout()).last(mainPanel2);
cancerCount = 11;
break;
case "Previous":
((CardLayout) mainPanel2.getLayout()).previous(mainPanel2);
cancerCount--;
cancerCount = cancerCount < 1 ? 11 : cancerCount;
break;
case "Next":
((CardLayout) mainPanel2.getLayout()).next(mainPanel2);
cancerCount++;
cancerCount = cancerCount > 11 ? 1 : cancerCount; //
break;
}
cancerList.setSelectedIndex(cancerCount-1);
}
}
/**
* Inner class that responds to any user interaction with a JComboBox for
* general types of cancers.
*/
public class CancerItemListener implements ItemListener {
#Override
public void itemStateChanged(ItemEvent e) {
JPanel showPanel = new JPanel();
if(e.getStateChange() == ItemEvent.SELECTED) {
String selection = (String) e.getItem();
if(selection.equalsIgnoreCase("skin cancer")) {
CancerPanels.skin skin = new CancerPanels.skin();
showPanel = skin.skinReturn();
} else if (selection.equalsIgnoreCase("bladder cancer")) {
CancerPanels.bladder bladder = new CancerPanels.bladder();
showPanel = bladder.bladderReturn();
} else if (selection.equalsIgnoreCase("pancreatic cancer")) {
CancerPanels.pancreatic pancreatic = new CancerPanels.pancreatic();
showPanel = pancreatic.returnPancreatic();
} else if (selection.equalsIgnoreCase("renal cancer")) {
CancerPanels.renal renal = new CancerPanels.renal();
showPanel = renal.returnRenal();
} else if (selection.equalsIgnoreCase("ovarian cancer")) {
CancerPanels.ovarian ovarian = new CancerPanels.ovarian();
showPanel = ovarian.ovarianReturn();
} else if (selection.equalsIgnoreCase("breast cancer")) {
CancerPanels.breast breast = new CancerPanels.breast();
showPanel = breast.returnBreast();
} else if (selection.equalsIgnoreCase("brain cancer")) {
CancerPanels.brain brain = new CancerPanels.brain();
showPanel = brain.returnBrain();
} else if (selection.equalsIgnoreCase("von hippel-lindau syndrome")) {
CancerPanels.vhlsPanels vhls = new CancerPanels.vhlsPanels();
showPanel = vhls.vhlsReturn();
}
JOptionPane.showMessageDialog(null, showPanel);
}
}
}
Seperate class where the JPanels are made before being added to CardLayout:
public class CancerPanels extends CancerGUI {
static String name;
static JPanel cards;
static CancerController _cons = new CancerController();
static String[] cancerData;
static JScrollPane treatmentsScroller = new JScrollPane(txtTreatments, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane causesScroller = new JScrollPane(txtCauses, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
static JScrollPane symptomsScroller = new JScrollPane(txtSymptoms, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
public static class aplPanel extends JPanel {
public JPanel aplReturn() {
treatmentsScroller.setViewportView(txtTreatments);
txtTreatments.setEditable(false);
causesScroller.setViewportView(txtCauses);
txtCauses.setEditable(false);
symptomsScroller.setViewportView(txtSymptoms);
txtSymptoms.setEditable(false);
cards = new JPanel(new GridLayout(6,1));
cancerData = _cons.readCancer(0);
resultName.setText(cancerData[0]);
txtSymptoms.setText(cancerData[1]);
txtCauses.setText(cancerData[2]);
txtTreatments.setText(cancerData[3]);
resultRate.setText(cancerData[4]);
resultPrognosis.setText(cancerData[5]);
cards.add(resultName);
cards.add(symptomsScroller);
cards.add(causesScroller);
cards.add(treatmentsScroller);
cards.add(resultRate);
cards.add(resultPrognosis);
return cards;
}
In essence what you are trying to do is to change the state of one class from another.
How this is done with Swing GUI's is no different for how it is done for non-GUI programs: one class calls the public methods of another class.
One key is to have wiring to allow this to occur which means references for one class needs to be available to the other class so that appropriate methods can be called on appropriate references. The devil as they say is in the details.
"1) How do I get the JPanels to switch using CardLayout?" -- So the class that holds the CardLayout could for instance have the public methods, next(), previous(), and perhaps show(SOME_STRING_CONSTANT) or some other swapView(...) method.
"2) How do I get the data to be displayed in the GUI in text fields when a user clicks an item from the JList?" -- This will involve the use of listeners -- the class holding the JTextFields will listen for notification from the class that holds the JList, and when notified gets the necessary information from the list-displaying class. A PropertyChangeListener could work well here.
e.g.,
public class CancerSelectionListener implements ListSelectionListener {
private CardDisplayingView cardDisplayingView = null;
public CancerSelectionListener(CardDisplayingView cardDisplayingView) {
this.cardDisplayingView = cardDisplayingView;
}
#Override
public void valueChanged(ListSelectionEvent e) {
int selection = ((JList) e.getSource()).getSelectedIndex();
if(selection == 0) {
if (cardDisplayingView != null) {
cardDisplayingView.swapView(...);
}
}
}
}
My code is quite simple actually. I saw a simple and similar code was from this article.
At first, I have 1 combobox. I have a listener on it called itemStateChanged(). My purpose to add into this listener is that; "to execute some code when user click (select) an item from its dropbox".
Cmb_ItemCategory = new javax.swing.JComboBox();
Cmb_ItemCategory.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Loading..." }));
Cmb_ItemCategory.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
Cmb_ItemCategoryItemStateChanged(evt);
}
});
private void Cmb_ItemCategoryItemStateChanged(java.awt.event.ItemEvent evt) {
if(evt.getStateChange() == java.awt.event.ItemEvent.SELECTED){
System.err.println("Sombody click or change my model content");
}
}
Behind the code, I grab some data, and then calling a method of removeAllItems() .
And then I set a new Model (from new data) into it.
-- at another line of code ---
Cmb_ItemCategory.removeAllItems();
Cmb_ItemCategory.setModel(newModel);
I juz realized that my itemStateChanged() is called when i do the removeAllItem() method. called once.
So, How to make it only called once user Click (select) only AND not when removeAllItems() called?
it similar to this article. But it's not removingItems case. CMIIW.
Here check this code out, this works flawlessly, might be you doing something wrong where you calling removeAllItems() :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ComboState
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Combo State Testing : ");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final JComboBox cbox = new JComboBox();
cbox.addItem("One");
cbox.addItem("Two");
cbox.addItem("Three");
cbox.addItem("Four");
cbox.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent ie)
{
if (ie.getStateChange() == ItemEvent.SELECTED)
{
System.out.println("Item Selected is : " + ie.getItem());
}
/*else
{
System.out.println("I am called for other reasons.");
}*/
}
});
/*
* Click me to remove JComboBox's items.
*/
JButton removeButton = new JButton("REMOVE");
removeButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
cbox.removeAllItems();
}
});
frame.add(cbox, BorderLayout.CENTER);
frame.add(removeButton, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ComboState().createAndDisplayGUI();
}
});
}
}
As nIcE cOw already illustrated in his example, it should certainly work when you use a DefaultComboBoxModel (which is the case in his sample code, although it happens behind the screens).
I could explain the behavior you encounter for the non-DefaultComboBoxModel case, although your code snippet suggests you use one. Looking at the source code for JComboBox#removeAllItems there is a different code path since the removeAllElements method is not part of the MutableComboBoxModel interface
public void removeAllItems() {
checkMutableComboBoxModel();
MutableComboBoxModel<E> model = (MutableComboBoxModel<E>)dataModel;
int size = model.getSize();
if ( model instanceof DefaultComboBoxModel ) {
((DefaultComboBoxModel)model).removeAllElements();
}
else {
for ( int i = 0; i < size; ++i ) {
E element = model.getElementAt( 0 );
model.removeElement( element );
}
}
selectedItemReminder = null;
if (isEditable()) {
editor.setItem(null);
}
}
So with a non-DefaultComboBoxModel you are going to remove the items one by one. This means that at a certain point in time, you will remove the selected element. A possible implementation of your model might change the selected element at that point. If you look for example at the implementation in DefaultComboBoxModel (although this code will not be triggered) you can clearly see it changes the selection.
public void removeElementAt(int index) {
if ( getElementAt( index ) == selectedObject ) {
if ( index == 0 ) {
setSelectedItem( getSize() == 1 ? null : getElementAt( index + 1 ) );
}
else {
setSelectedItem( getElementAt( index - 1 ) );
}
}
objects.removeElementAt(index);
fireIntervalRemoved(this, index, index);
}
Perhaps your model does something similar, which explains the event. Just for making this post complete, the code behind the DefaultComboBoxModel#removeAllElements where you can clearly see it sets the selection to null and does not select another object. Only weird thing in that code is that it does not fire a DESELECTED event first, although you know the selection has changed if you listen for the intervalRemoved event ... but that is not really relevant to your problem
public void removeAllElements() {
if ( objects.size() > 0 ) {
int firstIndex = 0;
int lastIndex = objects.size() - 1;
objects.removeAllElements();
selectedObject = null;
fireIntervalRemoved(this, firstIndex, lastIndex);
} else {
selectedObject = null;
}
}
So to conclude: I say the solution for your problem is located in your model, and not in the code you posted
One quick way to do is to have a bool set to true before you call removeAllItem() and back false after. Execute the code in your itemStateChanged() only if the bool variable is false.
Ideally you could override the removeAllItem() function.
not clear from whole discusion,
you have to remove all Listener(s) from JComboBox before removing all Items, after Items are removed you can add Listener(s) back,
still not sure if you want to add & remove Items dynamically, or you can set whatever value for another JComponent(s),
(against complicating simple things) did you see there remove,
.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class ComboBoxTwo extends JFrame implements ActionListener, ItemListener {
private static final long serialVersionUID = 1L;
private JComboBox mainComboBox;
private JComboBox subComboBox;
private Hashtable<Object, Object> subItems = new Hashtable<Object, Object>();
public ComboBoxTwo() {
String[] items = {"Select Item", "Color", "Shape", "Fruit"};
mainComboBox = new JComboBox(items);
mainComboBox.addActionListener(this);
mainComboBox.addItemListener(this);
//prevent action events from being fired when the up/down arrow keys are used
//mainComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
getContentPane().add(mainComboBox, BorderLayout.WEST);
subComboBox = new JComboBox();// Create sub combo box with multiple models
subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4
subComboBox.addItemListener(this);
getContentPane().add(subComboBox, BorderLayout.EAST);
String[] subItems1 = {"Select Color", "Red", "Blue", "Green"};
subItems.put(items[1], subItems1);
String[] subItems2 = {"Select Shape", "Circle", "Square", "Triangle"};
subItems.put(items[2], subItems2);
String[] subItems3 = {"Select Fruit", "Apple", "Orange", "Banana"};
subItems.put(items[3], subItems3);
// mainComboBox.setSelectedIndex(1);
}
#Override
public void actionPerformed(ActionEvent e) {
String item = (String) mainComboBox.getSelectedItem();
Object o = subItems.get(item);
if (o == null) {
subComboBox.setModel(new DefaultComboBoxModel());
} else {
subComboBox.setModel(new DefaultComboBoxModel((String[]) o));
}
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (e.getSource() == mainComboBox) {
if (mainComboBox.getSelectedIndex() != 0) {
FirstDialog firstDialog = new FirstDialog(ComboBoxTwo.this,
mainComboBox.getSelectedItem().toString(), "Please wait, Searching for ..... ");
}
}
}
}
private class FirstDialog extends JDialog {
private static final long serialVersionUID = 1L;
FirstDialog(final Frame parent, String winTitle, String msgString) {
super(parent, winTitle);
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
JLabel myLabel = new JLabel(msgString);
JButton bNext = new JButton("Stop Processes");
add(myLabel, BorderLayout.CENTER);
add(bNext, BorderLayout.SOUTH);
bNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
t.setRepeats(false);
t.start();
setLocationRelativeTo(parent);
setSize(new Dimension(400, 100));
setVisible(true);
}
}
public static void main(String[] args) {
JFrame frame = new ComboBoxTwo();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The method removeAllItems does not call ItemStateChanged, but it call actionPerformed, you can check it by running this simple code:
public class Tuto {
public static void main(String[] args) {
//create the main frame
JFrame frame = new JFrame();
frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setLocation(new Point(10, 10));
frame.setPreferredSize(new Dimension(400, 300));
JComboBox<String> combo = new JComboBox();
combo.addItem("item 1");
combo.addItem("item 2");
combo.addItem("item 3");
combo.setBounds(50, 30, 300, 20);
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println(" action Performed ");
}
});
frame.add(combo);
JButton button = new JButton("Remove");
button.setBounds(50, 100, 100, 30);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
combo.removeAllItems();
}
});
frame.add(button);
frame.pack();
frame.setVisible(true);
}
}