JComboBox remembering other selections - java

I have a JTable and in one column I have a JComboBox for each of the rows. I am dynamically adding rows when I press a button. The selection made in the combobox will determine what calculation is carried out for that particular row. For arguments sake lets say that the options for the combobox are: option 1, option 2, option 3 and option 4.
The issue I am having is as follows:
Say I have added 2 rows and select any option from the combobox for row 1, when I go to make a selection in the combobox for row 2 the same selection is ticked as was made for row 1. There seems to be some kind of memory. How can I disable this, so that the default selection is always -1 (i.e. non of the options selected)? I would like to have complete control over this.
Here is an example snippet of code just considering option 1:
String labels[] = {"Option 1", "Option 2", "Option 3", "Option4"};
JComboBox comboBox = new JComboBox(labels);
comboBox.setSelectedIndex(-1);
ItemListener itemListener = new ItemListener() {
public void itemStateChanged(ItemEvent itemEvent) {
int state = itemEvent.getStateChange();
ItemSelectable is = itemEvent.getItemSelectable();
if (selectedString(is) == "Option 1" & state == ItemEvent.SELECTED){
System.out.println("A");
}
}
};
comboBox.addItemListener(itemListener);
Thanks very much for your time and help :)

First of all don't use "==" when comparing strings. Instead you should be using the equals(...) method:
if (someString.equals(anotherString))
// do something
However, that is not the cause of the problem.
You are using the JComboBox incorrectly for a JTable. You should NOT be using a ItemListener (or any listener).
The combo box is just used as an editor for the table. That means when you select a value from the combo box, the TableModel of the table is updated. So if you have custom logic based on the selected value you need to override the setValueAt(...) method of your TableModel.
#Override
public void setValueAt(Object value, int row, int column)
{
super.setValueAt(value, row, column);
// add your custom logic here
}
How can I disable this, so that the default selection is always -1
The value displayed in the combo box is taken from the TableModel. So if you set the default value to be null the combo box will not have a selection when you start editing.
Read the section from the Swing tutorial on How to Use Tables for more information and working examples. Keep the tutorial link handy for future reference on Swing basics.

Related

JTable dynamic listener

Things that i am trying to achieve:
Select the row and add in values, the first value at col=0 will determine what will generate at col=2 and what col=2 value is will generate values for col=3.
To achieve what i have said on the selected row, for example if i have more than 2 rows of data which is empty. When i fill in the first row of data, the second row of data should be remain untouched. The second row of values are only generated when i click of the second row value.
Lastly this is just another button that i have which is a "save" button where it will retrieve the data from the table and store it. However i am getting this problem where when my mouse is still selected on the cell, that selected cell value is not being passed in and stored. So is there a way when i click the button, i can deselect the cell?. Side note i have used clearSelection and it does not work.
Currently what i have:
At the moment i managed to do the change where when i click a value from the col=0 and it will update the value for col=1. However i am now stuck at how i am going to get the value from the col=1 to generate my values for col=3 which is the last col. I have tried adding another if else in the method however that does not work.
At the moment the values i add in are combobox these combobox values are derived from a method that passes in the selection choice of the values from their respective cols.
Method for table listener:
public static void TableListen(JTable Model,SQLObject so){
Model.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent evt) {
if(Model.getModel().getRowCount()!=0){
if(Model.getSelectedColumn()==0){
if(!Model.getModel().getValueAt( Model.getSelectedRow(), 0).toString().equals("-Selection-")){
String treatmentChoice=Model.getModel().getValueAt(Model.getSelectedRow(), Model.getSelectedColumn()).toString();
JComboBox<String> comboBox = null;
TableColumn feedingCol=Model.getColumnModel().getColumn(1);
comboBox=DosageObject.GetListOfMedication(so,treatmentChoice);
feedingCol.setCellEditor(new DefaultCellEditor(comboBox));
}
}
}
}
});
}

How to add a custom checkbox into JList (Java)?

This is how the program looks:
This is how I want it to look:
As you can see in the picture I have tried a bit and learned that I need to use ListCellRenderer, but the problem is i have created 2 custom png files
checked.png and
unchecked.png
when I click daily goals #1 it should give state = true and checked.png should appear and stay checked unless I click it again. Unchecked.png could be standard on the jList column.
I also want to place my checkbox 1 cm to the left of the end of the row (padding) not sure hows its done in java sadly. (You'll understand better by looking at the picture)
After looking through some guides I have learned that the only way to add extra stuff to a JList column is by using ListCellRenderer. I have tried quite a while with no success so thought of asking others. Does anyone have any ideas on how to do this?
The thought was to get it to work then display in a JTable by changing the Jtable column to Daily goals and displaying X to indicate the goal was achieved. But I think I should be able to do this, The main question is the custom checkbox implementation.
You can have two types of checkboxes to be used as jlist cell renderers, one for selected cells, another for unselected.
Use ImageIcon to decorate the checkbox with your images.
In your jlist cell render you need to have logic to return the intended checkbox to render that list cell.
Note to override the text in the checkbox to the actual list cell value
public class TestFrame extends JFrame {
ImageIcon iconChecked = new ImageIcon(TestFrame.class.getResource("checked.png"));
ImageIcon iconUnchecked = new ImageIcon(TestFrame.class.getResource("unchecked.png"));
JList jList = new JList(new Object[]{"ABC", "123"});
public TestFrame() {
this.add(jList);
jList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
jList.setCellRenderer(new ListCellRenderer() {
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
for (int i : list.getSelectedIndices()) {
if (index == i) {
JCheckBox checkBoxChecked = new JCheckBox(value.toString(), iconChecked);
return checkBoxChecked;
}
}
JCheckBox checkBoxUnchecked = new JCheckBox(value.toString(), iconUnchecked);
return checkBoxUnchecked;
}
});
}}

JTable JComboBox is defaulting to display 1st item when list is expanded

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

getSelectedRow on a combobox cell editor

I need a listener on a CombobBox which is a cellEditor on a JTable.
This listener must give me the new selected value and the row id.
Problem with my below solution is that the listner is linked to all rows, so when I change one ComboBox value in one row, then move to another row (with a different combo value) an event is raised, but the selected row has not yet changed. How can I get rid of this case ?
Thanks
column = jTableCheck.getColumnModel().getColumn(9);
JComboBox comboBox = new JComboBox(comboGenre);
comboBox.addItemListener(new ItemListener(){
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
int row = jTableCheck.getSelectedRow();
Popup.info(e.getItem() + " SELECTED, row="+row);
}
}
});
column.setCellEditor(new DefaultCellEditor(comboBox));
Don't use an ItemListener on the combo box.
Instead you should be using a TableModelListener. An event will be fired whenever the data in the TableModel is changed. So you add the TableModelListener to the TableModel of your JTable.
The TableModelEvent will give your row/column of the cell that changed. You can get the changed value from the TableModel.
Or maybe you would want to use a Table Cell Listener which is similar to the TableModelListener except the code is only invoked when the value is actually changed and you use an Action to do the processing.
In fact, I already used a TableCellListener on another table, but forgot about that!
I found out a usefull class here: http://tips4java.wordpress.com/2009/06/07/table-cell-listener/

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

Categories

Resources