I wnt that when i enter some letter in the textfield then the related items should be picked up from my database and should appear as a drop down list.
For Example:
I typed 'J' in text Field, in my database is having names such as {"Juby','Jaz','Jasmine','Joggy'....}
Theses names should appear as a list. So that i could select one from them.and so on for other leters as well.
Is there any predefined control in awt??
Thnx
Why not just use a JComboBox? By default, when the user types a keystroke in a read-only combobox and an item in the combobox starts with the typed keystroke, the combobox will select that item.
Or you could set the JComboBox to be editable using setEditable(true), and use a KeySelectionManager. The link explains selecting an item in a JComboBox component with multiple keystrokes.
This is a small example implementing what ( i think) you asked for.. the database in this example is a vector of strings.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Answer extends JFrame {
public static final int MAXITEMS = 100;
JPanel panel = new JPanel();
JTextField textField = new JTextField(10);
String[] myDataBase = { "Juby", "Jaz", "Jasmine", "Joggy", "one", "dog","cat", "parot" };
String[] listItems;
JList theList = new JList();
public Answer() {
this.add(panel);
panel.setPreferredSize(new Dimension(500, 300));
panel.add(textField);
panel.add(theList);
textField.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent ke) {
String compareString = ("" + textField.getText() + ke.getKeyChar());
listItems = new String[MAXITEMS];
if (compareString.trim().length() > 0 ){
int counter = 0;
for (int i = 0; i < myDataBase.length; i++) {
if (counter < MAXITEMS) {
if (myDataBase[i].length() >= compareString.length() &&
myDataBase[i].substring(0, compareString.length()).equalsIgnoreCase(compareString)) {
listItems[counter] = myDataBase[i];
counter++;
}
}
}
}
theList.setListData(listItems);
}
});
}
public static void main(String[] args) {
final Answer answer = new Answer();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
answer.pack();
answer.setVisible(true);
}
});
}
}
One option is to use GlazedLists, as it has some support for auto-completion.
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);
I'm making an auction game and i'm going to display an item for the user to bid on. if the user doesnt like that item, he bids for another item by clicking the next item button. Another item is then displayed. This is where the problem is. When i write a continue statement in the action listener for the button, it says continue cannot be used outside of a loop.
Again, I very much doubt that you'll want to use a while loop in this situation. Instead you'll likely hold the items in a collection such as an ArrayList or a simple array, have an int index variable, and increment the index when the button is pressed and then retrieve the next item in the collection using the newly advanced index. For example
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class NextItem extends JPanel {
private static final String[] ITEMS = { "Sun", "Mon", "Tues", "Wed",
"Thurs", "Fri", "Sat" };
private JTextField displayField = new JTextField(10);
private JButton nextBtn = new JButton(new NextAction("Next"));
private int itemsIndex = 0;
public NextItem() {
displayField.setText(ITEMS[itemsIndex]);
displayField.setFocusable(false);
add(displayField);
add(nextBtn);
}
private class NextAction extends AbstractAction {
public NextAction(String name) {
super(name); // give button its text
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic); // give button a hot key
}
#Override
public void actionPerformed(ActionEvent e) {
itemsIndex++; // advance index
itemsIndex %= ITEMS.length; // renormalize it -- set to 0 if too large
displayField.setText(ITEMS[itemsIndex]);
}
}
private static void createAndShowGui() {
NextItem mainPanel = new NextItem();
JFrame frame = new JFrame("NextItem");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have 20 loop-generated JToggleButtons and I need to count how many of them are active.
private void generarBotones(){
JToggleButton b;
this.panelCuerpo.setLayout(new GridLayout(4,5));
for(int i = 1; i<=20; i++){
b = new JToggleButton();
b.setText(String.valueOf(i));
this.panelCuerpo.add(b);
b.addActionListener(new ActionListener() {
int clicks = 0;
#Override
public void actionPerformed(ActionEvent ae2){
clicks = clicks + 1;
System.out.println(clicks);
}
public void setCantidadBoletas(int clicks){
cantidadBoletas = clicks;
}
});
}
}
The problem here is that it counts how many times is EACH ONE of them clicked instead of count how many of them are selected.
PS. I tried to use (b.isSelected()) but b needs to be final to access it so it wasn't the solution.
If you declare the JToggleButton inside the loop, you can make it final:
for (int i = 1; i<=20; i++) {
JToggleButton b = new JToggleButton();
Then you can use b.isSelected:
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (b.isSelected())
clicks++;
else
clicks--;
}
});
}
clicks would have to be a class variable.
Suggestions:
Create a field, JToggleButton[] toggleButtons = new JToggleButton[20]
Or use an ArrayList if you so choose
In your for loop create your JToggleButton and assign it to the proper array item.
In the ActionListener simply iterate through the array, counting how many of its JToggleButton items are selected.
You're done.
Create a class attribute that will count the selected toggles:
private int selectedCount;
Initialize the counter to 0 in your constructor:
this.selectedCount = 0;
Increment or decrement the counter every time the state of a toggle changes:
b.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
if (ev.getStateChange() == ItemEvent.SELECTED){
YourClass.this.selectedCount++;
} else if (ev.getStateChange() == ItemEvent.DESELECTED){
YourClass.this.selectedCount--;
}
System.out.println(YourClass.this.selectedCount);
}
});
There are many ways to get this done and the best way depends on the rest of your code. I tried to keep it as close to yours.
You can just declare the buttons as final inside the loop and keep a global count of the number of buttons selected, which will be modified in the ActionListener:
public class ButtonsCount extends JFrame {
int clicks = 0;
ButtonsCount() {
JLabel label = new JLabel("0");
JPanel buttonsPanel = new JPanel(new GridLayout(4,5));
for(int i = 1; i <= 20; i++) {
final JToggleButton b = new JToggleButton();
b.setText(String.valueOf(i));
buttonsPanel.add(b);
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae2){
if (b.isSelected())
label.setText(String.valueOf(++clicks));
else
label.setText(String.valueOf(--clicks));
}
});
}
add(buttonsPanel);
add(label, BorderLayout.PAGE_END);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new ButtonsCount();
}
}
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);
}
}