Selecting Items in JComboBox - java

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);
}
}
});

Related

Getting input from multiple button groups in Java

I have an array of question, an array of possible answers and an array of properties I want to find out by answering the questions
String[] questions = new String[]{"Question1", "Question2", "Question3"};
String[] possibleAnswers = new String[]{"yes,no", "yes,no", "big,small"};
String[] properties = new String[]{"", "", ""};
I created a label for every question and JRadioButtons for every answer for that question by using split on the corresponding element in the possibleAnswers array.
for (int i = 0; i < questions.length; i++) {
//label that holds the current question
JLabel questionLabel = new JLabel(questions[i]);
questionPanel.add(questionLabel);
// string that holds answers for current question i.e. {yes, no}
String[] currentQuestionAnswers = possibleAnswers[i].split(",");
ButtonGroup buttonGroup = new ButtonGroup();
for (int j = 0; j < currentQuestionAnswers.length; j++) {
JRadioButton btnRadio = new JRadioButton(currentQuestionAnswers[j]);
// action listener that will store the selected answer and the question
btnRadio.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
answer = btnRadio.getText();
// some code that moves answer at the right index in the properties array
}
});
buttonGroup.add(btnRadio);
questionPanel.add(btnRadio);
}
}
This image shows what I want it to look like.
For each question I want to find a property. Let's say {Question1, Question2, Question3} are actually these questions {"talks?", "expensive?", "dimension?"}. When I get the text from the selected buttons, I'll have talks -> yes, expensive -> no, dimension -> big, so the properties array will become {"yes", "no", "big"}.
I know how to get the selected answer, but I can't figure out how to find the question that corresponds to that answer. I thounght I can somehow use the button groups I created, but I don't know how.
I hope this makes sense and someone can help. Thank you.
One way to do it would be to extend JRadioButton and add a simple ID field (a tag). I can't test this code right now but I think
it should work.
class MyRadioButton extends JRadioButton{
private int tag;
public getTag(){ return tag;}
public setTag(int val){ tag = val}
}
And then in the actionPerfomed method, just check this tag and take an appropriate action based on it.
int tag = 0;
btnRadio.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
answer = btnRadio.getText();
switch(btnRadio.getTag()){
case 0:
//do some action
break;
case 1:
....
}
// some code that moves answer at the right index in the properties array
}
});
btnRadio.setTag(tag++);//this will set a unique tag for each radio button
buttonGroup.add(btnRadio);
Alternatively, if you don't want to extend JRadioButton,which arguably might be overkill for your use case, you can use RadioButton.setActionCommand and ActionEvent.getActionCommand
btnRadio.setActionCommand("some_unique_string")
and then just check this command string in actionPerformed
if("some_unique_string".equals(ae.getActionCommand())
//do something

How to know what you selected in the JComboBox

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
}
}
);

Two JComboBoxes user can't choose same value

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.

JTable boolean values not updating when using JOptionPane

I'm trying to write a bit of code that can allow the user to fill in text fields by clicking on boolean cells in a JTable.
I can get the program to enter the data from the table into a text-field but my current method of doing this involves a JOptionPane which for some strange reason stops the table from changing the check-box values (i.e. the check-box doesn't change from black to ticked). Not only this but the selection doesn't update so the value in the last column remains false, even though the selection should switch it to true.
I think it might be something to do with the JOptionPane somehow overriding the selection event, but I don't know enough about the JOptionPane object to say how. My code is:
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
ListSelectionModel selectionModel = table.getSelectionModel();
selectionModel.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel) e.getSource();
if (lsm.isSelectionEmpty()) {
//no rows are selected do nothing
} else {
//First find the row clicked
int selectedRow = lsm.getLeadSelectionIndex();
/*
* put a popup here to ask the user which peak to associate
* the energy with.
*/
System.out.println(selectedRow);
//Get user to associate with a peak
availablePeaks = getAvailablePeaks();
String returnVal = (String) JOptionPane.showInputDialog(
null,
"Select the peak:",
"Peak Matching",
JOptionPane.QUESTION_MESSAGE,
null,
availablePeaks, null);
System.out.println(returnVal);
//Determine the selection
int index = 0;
for (int i = 0; i < availablePeaks.length; i++) {
if (availablePeaks[i] == returnVal) {
index = i;
} else {
}
}
//Set the peak value in the peak specifier to the energy in the row
double energy = (Double) table.getValueAt(selectedRow, 0);
System.out.println(energy);
frame.getPeakSetter().getPeakSpecifiers()[index].setEnergy(energy);
frame.getPeakSetter().getPeakSpecifiers()[index].getTextField().setText("" + energy);
}
}
});
Does anyone know why a JOptionPane in the ListSelectionListener would stop the table from updating the check-boxes?
Thanks!
I assume that your model returns true for isCellEditable() and that getColumnClass() returns Boolean.class for the JCheckBox column. This enables the default rednerer/editor, listed here.
It looks like the gesture of selecting the row is bringing up the dialog. It's not clear how this prevents the DefaultCellEditor from concluding; it works for me. As you are not checking getValueIsAdjusting(), I'm surprised you don't see two ListSelectionEvent instances.
In any case, bringing up a dialog each time the selection changes seems cumbersome. Several alternatives are possible:
Keep the ListSelectionListener, make the cell non-editable by returning false from isCellEditable(), and set its value in the model only if the dialog concludes successfully.
Drop the ListSelectionListener in favor of a JButton editor, shown here.
Drop the ListSelectionListener in favor of a custom CellEditor, as outlined below.
table.setDefaultEditor(Boolean.class, new DefaultCellEditor(new JCheckBox()) {
#Override
public boolean stopCellEditing() {
String value = JOptionPane.showInputDialog(...);
...
return super.stopCellEditing();
}
});

Multiple selection and JPopupMenu on right click

I am having problems with a popup menu on a JTable and the fact that this JTable allows for Multiple Interval Selection.
I'm going to explain in detail my situation, making it as clear as possible, hopefully.
I have a basic data class, lets call it Item, with a string id (name) and two boolean fields, online and active (with relative getters).
The idea behind the JTable is that, for each item in the dataset, it will show its name in the first colum and its status in the second column, where by 'status' I mean that, it will show "ACTIVE/NOT ACTIVE" if the Item is Online, otherwise it will show "OFFLINE".
I have implemented a TableModel that does the job and it works.
I also want, when the user right clicks on a row, a popup to appear (if the selected Item is ONLINE) allowing to Activate/Deactivate the item, depending on its status.
This worked perfectly as long as the Selection Model was SINGLE SELECTION, but when I changed it to MULTIPLE INTERVALS SELECTION, I could not make it work properly anymore.
The behaviour that I want is that, on right-click, a popup appears where the click is performed, the row is added to the selection and highlighted and all the previously selected rows stay selected! This I cannot manage to do!
Here is the code I have in the MouseListener:
tblModel.addMouseListener(new MouseAdapter() {
void showPopup(MouseEvent e){
int r = tblModel.rowAtPoint(e.getPoint());
if (r >= 0 && r < tblModel.getRowCount()) {
//tblModel.setRowSelectionInterval(r, r);
} else {
tblModel.clearSelection();
}
int[] viewRowIndexes = tblModel.getSelectedRows();
int rowViewIndex = tblModel.getSelectedRow();
if (rowViewIndex < 0)
return;
int rowModelIndex = tblModel.convertRowIndexToModel(rowViewIndex);
if (e.isPopupTrigger() && e.getComponent() instanceof JTable) {
Action changeActiveAction;
Action changeInactiveAction;
List<String> actives = new ArrayList<String>();
List<String> inactives = new ArrayList<String>();
DefaultListSelectionModel selectionModel = (DefaultListSelectionModel) tblModel.getSelectionModel();
for (int viewRowIndex : viewRowIndexes) {
int modelRowIndex = tblModel.convertRowIndexToModel(viewRowIndex);
if (selectionModel.isSelectedIndex(viewRowIndex)) {
boolean online = ((MyTableModel) tblModel.getModel()).isItemOnline(modelRowIndex);
if (!online)
continue;
boolean active = ((MyTableModel) tblModel.getModel()).isItemActive(modelRowIndex);
String idItem = (String) ((MyTableModel) tblModel.getModel()).getValueAt(modelRowIndex,0);
if (active) {
actives.add(idItem);
} else {
inactives.add(idItem);
}
}
}
if (actives.size() > 0 || inactives.size() > 0) {
popup = new JPopupMenu();
if (actives.size() > 0) {
changeActiveAction = new ChangeAction("Deactivate ACTIVE Items","This will deactivate all the selected ACTIVE items",actives, false);
popup.add(new JMenuItem(changeActiveAction));
}
if (inactives.size() > 0) {
changeInactiveAction = new ChangeAction("Activate INACTIVE Items","This will activate all the selected INACTIVE items",inactives, true);
popup.add(new JMenuItem(changeInactiveAction));
}
popup.show(e.getComponent(), e.getX(),e.getY());
}
}
}
#Override
public void mousePressed(MouseEvent e) {
showPopup(e);
}
#Override
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
};
The behaviour is functionally correct, but the selection of rows is not working.
Having commented the line
//tblModel.setRowSelectionInterval(r, r);
when I right-click on a row, a popup appears, but it ignores the row on which I clicked.
On the other hand, if uncommented, that line will select only the clicked row, losing all the rest of the selection....
I am sorry for the long post, but I didn't know how to explain my problem without giving all the details of my situation....
Hopefully this is a trivial thing and you can tell me how I can fix/change it.
Thank you in advance.
One part of the answer is:
if (tblModel.isSelectedIndex(r)) {
tblModel.removeSelectionInterval(r, r);
} else {
tblModel.addSelectionInterval(r, r);
}

Categories

Resources