I've got two JComboBox. First one has model with elements "one", "two", "three" and second has model with elements "three", "four". And when user choose element "three" in first JComboBox, he can't choose element "three" in second one JComboBox. And in reverse - when user choose element "three" in second one JComboBox, he can't choose same element in first one CB. How can i do this in Java ?
Thank you for answers.
One more question. When i dynamically create ComboBoxes (when someone clicked the button - in button actionListener), and every new ComboBox has same model - same list of elements. How can i check this case ? Same like Blip said ?
In my opinion you could add ItemListener to the 2 JComboBox. If the user selects the object "three" in any of the JComboBox then the object "three" could be removed from the other JComboBox's model. And if the user deselects the object "three" in one JComboBox then the object "three" can be added to the model of the other JComboBox.
You could implement in the following way:
Lets have have the two JComboBox stored in variables box1 and box2 which could be implemented as :
JComboBox<String> box1 = new JComboBox<>(new String[]{"one", "two", "three"});
JComboBox<String> box2 = new JComboBox<>(new String[]{"three", "four"});
Now add itemListener to both these JComboBox and pass it to a method say boxItemSelected:
box1.addItemListener(new ItemListener(){
itemStateChanged(ItemEvent e){
boxItemSelected(e);
}
});
box2.addItemListener(new ItemListener(){
itemStateChanged(ItemEvent e){
boxItemSelected(e);
}
});
Now to implement the boxItemSelected(e)
void boxItemSelected(ItemEvent e){
//Check the item selected/deselected is "three" else do nothing.
if (e.getItem().equals("three")){
//Find the box on which this action was not performed to change its model.
JComboBox<String> oppositeBox;
if(e.getSource().equals(box1)){
oppositeBox = box2;
}else{
oppositeBox = box1;
}
//Check the item is selected or deselected to remove or add "three" to item list.
if(e.getStateChange() == ItemEvent.SELECTED){
oppositeBox.removeItem("three");
}else{
oppositeBox.addItem("three");
}
}
}
Addition Information
Here if you have more than 1 items that are overlapping and can be selected only in one JComboBox, a slight modification of the method boxItemSelected could be take care of your problem as Illustrate below:
Change the line in the above code from:
if (e.getItem().equals("three"))
to
if (e.getItem().equals("three") || e.getItem().equals("<new item>") || ....)
And change
oppositeBox.removeItem("three");
oppositeBox.addItem("three");
to
oppositeBox.removeItem(e.getItem());
oppositeBox.addItem(e.getItem());
Here under any circumstance the user cannot select the same items in both the JComboBox. And all these happen behind the scene without the knowledge of the user using the user-interface.
When i dynamically create ComboBoxes (when someone clicked the button
- in button actionListener), and every new ComboBox has same model - same list of elements. How can i check this case ? Same like Blip said
?
In response to the above I am considering that all the items in all the JComboBox same and are stored in a List variable, and if 1 item is selected in any one of the JComboBox then that item cannot be selected in rest of the JComboBox. If my assumption is correct, then I suggest you do the following:
Create a List<JComboBox<?>> say boxes and initialise it as below:
List<JComboBox<?>> boxes = new ArrayList<>();
In your JButton (the button that dynamically JComboBox) variable's ActionListener implementation create a variable say items as an instance of List to store the items of the JComboBox and add the items
List<String> items = new Vector<>();
items.add("One");
items.add("Two");
......
Now remove the items from from the items variable that are selected in other JComboBox that are dynamically generated:
Iterator<JComboBox<?>> iterator = boxes.iterator();
while(iterator.hasNext()){
JComboBox<?> existing = iterator.next();
items.remove(existing.getSelectedItem());
}
Now after initialisation of the JComboBox instance say box set the Model of the box to the previously initialised and trimmed List variable items
box.setModel(new DefaultComboBoxModel(items));
now add the JComboBox variable box to the List variable boxes:
boxes.add(box);
Also in this above mentioned ActionListener implementation add the ItemListener to box, the newly instantiated variable of JComboBox and pass it to the method boxItemSelected:
box.addItemListener(new ItemListener(){
itemStateChanged(ItemEvent e){
boxItemSelected(e);
}
});
Now the implementation of the boxItemSelected has to be changed to accommodate the changes:
void boxItemSelected(ItemEvent e){
//Create an iterator to iterate over the boxes
Iterator<JComboBox<?>> iterator = boxes.iterator();
while(iterator.hasNext()){
//Get the current instance of comboBox from the list
JComboBox<?> current = iterator.next();
//If the box in which the select or de-select
//event has occurred is the current comboBox then do nothing.
if(e.getSource().equals(current)(
continue;
}
//If the event is select then remove the Item from the
//current comboBox else add the Item to the current comboBox.
if(e.getStateChange() == ItemEvent.SELECTED){
current.removeItem(e.getItem());
}else{
current.addItem(e.getItem());
}
}
}
So this is definitely possible. The best way I think would be to check the selected index of both boxes and then perform your logic based on the results of that index value. In the example below you can see that demonstrated. What is happening is there is an ActionListener on ComboBox1 and 2. If the values match, I used index but you can also get the string value to make sure they don't match up.
public class SOF extends JFrame {
private JPanel mainPanel, comboPanel;
private JComboBox jcb1, jcb2;
public SOF()
{
super("Combo Box Example");
mainPanel = new JPanel();
mainPanel.add(configureCombo());
add(mainPanel);
setSize(200,200);
setLocationRelativeTo(null);
setVisible(true);
jcb1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
//You can replace this with, jcb2.getSelectedItem if you don't know the indexes or if they will be random.
if((jcb1.getSelectedIndex() == 2) && (jcb2.getSelectedIndex() == 0))
{
JOptionPane.showMessageDialog(null, "Cannot select 3 in both field.");
jcb1.setSelectedIndex(-1);
jcb2.setSelectedIndex(-1);
}
//ANOTHER OPTION
If((jcb1.getSelectedValue().equals("three") && (jcb2.getSelectedValue().equals("three")
{
LOGIC
}
}
});
jcb2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
//You can replace this with, jcb2.getSelectedItem if you don't know the indexes or if they will be random.
if((jcb2.getSelectedIndex() == 0) && (jcb1.getSelectedIndex() == 2))
{
JOptionPane.showMessageDialog(null, "Cannot select 3 in both field.");
jcb1.setSelectedIndex(-1);
jcb2.setSelectedIndex(-1);
}
}
});
}
private JPanel configureCombo()
{
String[] cb1List = {"one", "two", "three"};
String[] cb2List = {"three", "four"};
comboPanel = new JPanel(new GridLayout(1,2));
jcb1 = new JComboBox(cb1List);
jcb2 = new JComboBox(cb2List);
comboPanel.add(jcb1);
comboPanel.add(jcb2);
return comboPanel;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
SOF s = new SOF();
}
}
On either one if matching boxes are selected an error message will pop up and deselect both comboboxes.
You could futz with the combobox's model, but easier would be to just check the selected values when the user asks the program to accept the values, perhaps in the ActionListener of a JButton, and then if two of the same values have been selected, deselect them and warn the user with a JOptionPane. Alternatively, you could have code in listeners (either Actionlistener or ItemListener) added to both JComboBox's that check the other combobox's selected value to make sure that they are not the same, and if so, warn the user and deselect the erroneous selection.
Related
I am creating a JList using swing, I can display and select multiple items, also I can add a new element to it. However, when I select the first element of the list and add a new one to the top, I got two selected elements (the old one and the new one), but when I change the selection mode to single selection it works fine, is it possible to prevent this automatic selection and just keep the old one selected using multiple interval selection mode?
I used this link that contain an example using DataEventListner but I did not succeed to find a solution. Any help please?
Here is my list:
public static void main(String args[]) {
String labels[] = { "A", "B", "C", "D", "E", "F", "G", "H" };
JFrame frame = new JFrame("Selecting JList");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final DefaultListModel model = new DefaultListModel();
for (int i = 0, n = labels.length; i < n; i++) {
model.addElement(labels[i]);
}
JList jlist = new JList(model);
jlist.setSelectionMode(
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JScrollPane scrollPane1 = new JScrollPane(jlist);
frame.add(scrollPane1, BorderLayout.CENTER);
JButton jb = new JButton("add F");
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
model.add(0, "First");
}
});
frame.add(jb,BorderLayout.SOUTH);
frame.setSize(640, 300);
frame.setVisible(true);
}
I see that you basically copied the code in the link in your question. That example only deals with adding a single element to the JList when clicking the JButton. It does not deal with the JList selection[s]. I don't think the author of that example considered what happens when the user selects one or more elements in the JList before clicking the JButton.
I was able to reproduce the behavior described in your question. It may be a bug in the implementation of JList or ListSelectionModel. The way I fixed it is to add code to method actionPerformed() that handles any existing JList selections.
Here is my modified version of method actionPerformed(). Note that all the rest of the code is unchanged. First I save the indexes of all the selected rows. Then I clear the existing selections. Then I add the new element to the JList. Now I need to re-select the rows that were selected before I added the new element. But note that I need to increment each index by one, because there is a new element at index 0 (zero).
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
int[] indices = jlist.getSelectedIndices();
jlist.getSelectionModel().clearSelection();
model.add(0, "First");
for (int index : indices) {
jlist.getSelectionModel().addSelectionInterval(index + 1, index + 1);
}
}
});
From the documentation of JList#setSelectionMode(int):
ListSelectionModel.SINGLE_SELECTION - Only one list index can be
selected at a time. In this mode, setSelectionInterval and
addSelectionInterval are equivalent, both replacing the current
selection with the index represented by the second argument (the
"lead").
try jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
You can add this in your jb.addActionListner():
int x = jlist.getSelectedIndex();
jlist.clearSelection();
jlist.setSelectedIndex(x);
This should work just the way you want it to!
I have two combo boxes with a list of distance units to convert from/to. Now, when I want to choose eg. "Centimeter" from the ComboBox From (distance)..., I really don't need to have "Centimeter" in ComboBox To (distance)..., because it doesn't make sense to convert from centimeter to centimeter.
So when "Centimeter" is selected in From (distance)... I want it to be removed in To (distance)... ComboBox. But, when I change my selection (say "Meter"), I want "Centimeter" to be back and "Meter" disappear etc.
I managed to remove the selected item in To (distance)... box, but don't know how to return it back when I change my selection. Besides, when I change selection, the code below just removes the corresponding item in To (distance)... ComboBox.
Please guide me to the correct solution. Here is the corresponding code. I can give you the whole code if you need. Thank you!
private String[] convertFromDistance = {"From (distance)...", "Centimeter", "Inch", "Kilometer", "Knot", "Meter", "Mile", "Millimeter", "Yard"};
private String[] convertToDistance = {"To (distance)...", "Centimeter", "Inch", "Kilometer","Knot", "Meter", "Mile", "Millimeter", "Yard"};
private JComboBox fromListDistance, toListDistance;
fromListDistance.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String list = (String)fromListDistance.getSelectedItem();
for (int i=0; i<convertToDistance.length; i++) {
if (convertToDistance[i].equals(list)) {
toListDistance.removeItem(convertToDistance[i]);
//here should go the code for adding back the item if selection is changed
}
}
}
});
toListDistance = new JComboBox<String>(convertToDistance);
first thing you i should do in your problem is to know what is the selected choice from fromListDistance combo box ..
after that i have to refill the toListDistance combo box except for the choice that the user have selected ..
it's easy to do this with if statement
fromListDistance.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//saving the selected choice
String choise=fromListDistance.getSelectedItem().toString();
//here we remove all items from the combo box
toListDistance.removeAllItems();
for (int i = 0; i < convertToDistance.length; i++) {
String distance=convertToDistance[i];
//compare the selected choice with the convertToDistance[i]
if (choise.equals(distance)) {
continue;
}
toListDistance.addItem(distance);
}
}
});
I am making a Basic calculator app in java which has 2 JTextFields and 1 JComboBox. What i want to know if there is a way to let a JButton detect what you selected in the JComboBox, when i did it with the text field it looked something like this
static String divide = "/";
if (n == JOptionPane.OK_OPTION) {
if (symbol.getText().equals(divide)){
<code>
}
}
So is there a similar way to do this with JComboBoxs??
String[] symbols = {times, minus, plus, divide};
That's the JComboBox's content code.
You can get selected item from JComboBox with method .getSelectedItem().
Say you have String[] symbols = {times, minus, plus, divide}; as an input when constructing JComboBox (see constructor JComboBox(E[] items) )
JComboBox jcb = new JComboBox(symbols);
//you will see the string you selected
System.out.println(jcb.getSelectedItem());
Perhaps use action listener
String[] quantities1 = {"/","+"};
JComboBox comboBox = new JComboBox(quantities1);
comboBox.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
//do stuff when a section is performed
//you can use comboBox.getSelectedItem() to get the selected value
}
}
);
I have been trying to determine why my JComboBox is displaying the 1st item in the list through numerous Google searches, but I'm struggling to find relevant help. It could be that I don't know the correct terminology (hence the overly specific title of this question) and thus not finding the information that would explain my issue. I checked out the JComboBox API, and few of the listeners and models that it uses, but they did not seem likely candidates.
The JComboBox in question is inside a JTable, so I am not aware if that changes the default behaviour of it. The code I am using is as below:
//row and col are final due to usage inside anonymous inner class
public TableCellEditor getCellEditor(final int row, final int col)
{
String[] listItems = new String[arrayList.getSize()];
int i = -1;
for(String s : arrayList)
{
i++;
listItems[i] = s;
}
JComboBox<String> box = new JComboBox<>(listItems);
box.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
if(e.getItem().equals("Add/Edit Projectile"))
{
//Where Editor is a JFrame that will be opened
new Editor();
}
}
}
});
DefaultCellEditor list = new DefaultCellEditor(box);
}
Please note that the Arraylist in my program does not contain Strings, but instead a more complicated set of custom objects that I believe would distract from the main issue.
I haven't included a Renderer for JComboBox's in the JTable as I was happy enough with the way it appeared, and figured that my problem was more going to be something I have neglected to implement in the model/implemented wrong.
I've also provided a couple of screenshots to better portray my problem. The first image is when the JComboBox is not selected, and simply displaying the currently selected item.
The second image is when I have just clicked the JComboBox to bring up the list. As depicted, it will immediately bring up that first item, no matter what it is.
If anyone has any suggestions as to where to look/solutions, I would be very grateful.
EDIT
My particular table has two columns, where the left column is a variable name, and the right column is the value associated with the variable. The tables role is to display the properties of a selected object, where each value for different variable for different objects are likely to not be the same.
In this particular case, the cell displays a JComboBox with all the available Projectiles in the game we are making. Each enemy has a different type of projectile it defaults to. So when I click on a different enemy in our game area, the table will display all of their current properties (defaults if they have not been changed).
Enemies do have a getter for the Projectile, so I could determine what the currently selected enemy is, get it's projectile, do a toString() to find how it is to be represented in the list, and do a setValueAt().
The only problem is at the moment it is always selecting the first item in the list when the list is expanded.
Unless the values for the JComboBox are dynamically generated for each row, you should be able to just prepare the CellEditor ahead of time, for example...
JComboBox cb = new JComboBox(new String[]{"1", "2", "3", "4"});
DefaultCellEditor editor = new DefaultCellEditor(cb);
JTable table = new JTable(new DefaultTableModel(5, 1));
table.getColumnModel().getColumn(0).setCellEditor(editor);
This will set the selected value of the editor to the value of the cell when the editing process starts
Updated
In the case where the combobox values are dynamically generate per row, you could do something more like...
JComboBox cb = new JComboBox();
DefaultCellEditor editor = new DefaultCellEditor(cb) {
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JComboBox editor = (JComboBox) getComponent();
String[] listItems = new String[arrayList.getSize()];
int i = -1;
for (String s : arrayList) {
i++;
listItems[i] = s;
}
DefaultComboBoxModel model = new DefaultComboBoxModel(listItems);
editor.setModel(model);
editor.setSelectedItem(value);
return editor;
}
};
JTable table = new JTable(new DefaultTableModel(5, 1));
table.getColumnModel().getColumn(0).setCellEditor(editor);
Note the use of editor.setSelectedItem(value);, this will set the selected value to the cells current value...
You could also re-use the model, clearing it each time and re-filling it with new values. You might find this more efficient if you have a large number of rows as you won't need to constantly create a new model each time a cell is edited
Thow this is an oldie...
Your problem is most likely you don't implement "equals" in the class used in the combo.
The Combo needs to select the current item when it is being prepared and does so by iterating through the elements of the model and selects the first one that is equal to the value in the cell. If none is encountered then it leaves the combo as is (either first element or the last used element in a previous cell edit)
This is how you should default to the previously selected element:
//...
Object selectedItem = box.getSelectedItem();
//Add some elements to the jComboBox
box.setSelectedItem(selectedItem);
I have two combo box the items first one is (women and men).I want when user select women in first combo box the list of women's dress will appear in second combo box and when men is selected the list of men's dress will appear in second one.Can do this functionality by using JCombo box? if yes how can I do that give me example please.
any help will be appreciated.
Check out how to work with models in How to Use Combo Boxes and How to Use Lists totorials. According to a selection in the first combo box - rebuild, filter or perhaps replace the model of the second combo box. You can use/extend DefaultComboBoxModel - a default model used by a JComboBox. For example consider this snippet:
final JComboBox genderComboBox = null;
final JComboBox itemComboBox = null;
final DefaultComboBoxModel hisModel = new DefaultComboBoxModel(new String[]{"a", "b", "c"});
final DefaultComboBoxModel herModel = new DefaultComboBoxModel(new String[]{"x", "y", "z"});
genderComboBox.addActionListener (new ActionListener () {
public void actionPerformed(ActionEvent e) {
if ("Men".equals(genderComboBox.getSelectedItem())){
itemComboBox.setModel(hisModel);
} else {
itemComboBox.setModel(herModel);
}
}
});
Alternatively, upon selection in the first combo you can rebuild the items in the second one manually, ie: using JComboBox methods removeAllItems() and addItem().
You have to add event listener to the first combobox. This way you will know when its selection changes, you can interrogate it and fill your second combobox out with appropriate data.
More information is at http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html#listeners