Transfer Items from One JComboBox to another JComboBox - java

Hi I'm trying to transfer one object from one combobox to another and vice versa.
To accomplish this,
I use actionListeners or ItemListeners, to no luck that they dont answer my problems, or maybe there's just something wrong in my implementation.
Assuming we have to comboboxes, combobox1 and combobox2.
Basically,
1. I first add the selected item to another combobox (combobox2)
2. I remove the selected item on the first combobox (combobox1)
When trying to debug this, i found out that everytime i am on the step of removing items, the listener of the other combobox fires, which does the same steps as above. This results into a loop, that just deletes the item, and places it back to the original combobox.
When using the ItemListener, with the proper if conditions of being selected or not, it throws a bigger error. Guys please help me..
*on edit mode/currently making an SSCE

Found this, as suggested by sir mKorbel.
It did the trick, setting the model via setModel(DefaultComboBoxModel model) method doesnt trigger the ActionListener when it tries to add the contents of the model passed, versus the addItem(Object obj) method that fires the ActionListener causing the havoc that i described on my question above.
Thanks guys, and i learned about a new thing called DefaultComboBoxModels!

jComboBox12.removeAllItems();
for (int t = 0; t < jComboBox11.getItemCount(); t++)
{
jComboBox12.addItem(jComboBox11.getItemAt(t));
}

Related

How can I serialize a JComboBox selection?

I would like it so that if I pick something on the JComboBox, when I close it it's saved, and so when I re-open the program, whatever was last selected is still selected.
I faced this problem before in one of my GUI applications. What I've done is that I saved the JComboBox selection in a variable using getSelectedItem() function. And when I reopen the program, I set it out again at the same index using setSelectedItem(Object a).
I hope it helps you solve your problem.

ActionListener and dynamic(?) GUI

I've read through a dozen or so actionlistener/loop related questions here, but I'm not sure I've found my answer. I started on my first large Java project, a text RPG that's spiraled into around 5K lines of logic and game features which was functioning as intended using just the console - when I decided I'd try to build a Java swing GUI for it instead. Here's my problem:
I use a Room object which handles the description of where the player is at and also has an array of options for the player to choose next which it creates dynamically based on what cell the room's id is in on a csv file and what is beside it. I stopped outputting this to the console and instead started creating JButtons based on the options array like so:
public void showNarrate(){
add(dd,gridConstraints);
optionCopy.clear();
int i = 0;
for(JButton j : optionButtons){
//adding and formatting buttons to gridBagConstraint I also set actionCommand for each button to the triggerValue (ID of the next room which the button should take the player to)
}
//I tried using a copy of my JButton array here so I could have something to iterate over in actionListener after clearing out the original
//(Since it needs to be cleared so the next Room's buttons can be built after the player chooses an option)
for(JButton j : optionButtons){
optionCopy.add(j);
}
optionButtons.clear();
//dd is a seperate drawingComponent I used for outputting room descriptions which may be totally unnecessary at this point :/
dd.repaint();
setVisible(true);
}
Over in actionlistener (Same class) this is how I tried to swing it:
for(JButton j : optionCopy){
if(e.getActionCommand().equals(j.getActionCommand())){
Main.saveRoom = Main.currentRoom;
Main.currentRoom = j.getActionCommand();
System.out.println(Main.currentRoom);
}
}}
Then in my main class I call:
narrator.narrate(currentRoom, saveRoom); which takes care of some other logic concerning locked doors, encounters, etc.
Also in Main loop are some other methods related to autosave and tracking which rooms the player has visited. I know from other q/a i'v read on here that this is all pretty bad design, and I'm sttarting to understand that now, but my issue is this:
The first room of the game loads up fine, when I click a button it outputs to console(Just for testing) the correct trigger value of the room the button should be calling, so I'm getting that far, but how can I call the same method over again now?
-If I call narrate from actionListener it will wind up calling itself again and complain about ConcurrentModification.
-If I try to keep a loop going in my Main class it will keep looping and won't allow for the player to actually choose a button.
I've never used threads before, which I wonder might be the answer,and the closest thing to a related answer I've found is this:
Java: Method wait for ActionListener in another class
but I don't think moving actionListener to Main class would resolve my problem which is actionListener winding up calling itself recursively. And as for the observer-observable pattern... I just can't understand it :(
I appreciate any and all help, I've learned a LOT trying to make this thing work without seeking help as much as possible but this has stumped me.
Your loop in actionPerformed only checks whether a JButton exists in your optionList with the given actionCommand. However this can be done before actually doing something:
boolean contained = false;
for (JButton j : optionButtons)
if (j.getActionCommand().equals(e.getActionCommand()))
contained = true;
if (contained) {
// change room
}
now you can call narrate because you have finished iterating over the collection beforehand and will not get a ConcurrentModificationException

Java Swing - make two JLists "siblings" - i.e. only one item in either can be selected

I have a JPanel which contains two JLists - both can have an item in them selected - as expected.
What I'd love to be able to do is have it so that only one item in either to be selected
Can anyone help me with either
a) "marrying" them so this can be the case
b) giving me some tips for the best practice to write listeners which can preside over them both and unselect all the elements of one when the other is selected - I'd rather avoid this if possible as I can see it getting ugly!!
Thanks :)
I think the best solution, also for the user, is putting a radio button next with a category label to each list, so you clearly disable the other each time you select one.
I can imagine the user clicking values on the first list, then clicking on the next one and seeing all the values he clicked are gone, with logical frustration...
Then when you are taking the values from the form, just take the enabled ones
The listener is not that difficult nor ugly to write. I would
make sure the lists only support single selection
add the same selection listener to both lists' selection model
This listener can be implemented as
public void valueChanged(ListSelectionEvent e){
if ( e.isAdjusting()) return;
ListSelectionModel sourceSelectionModel = (ListSelectionModel) e.getSource();
if ( !sourceSelectionModel.isSelectionEmpty() ){
//still need to implement the findOtherSelectionModel method
ListSelectionModel other = findOtherSelectionModel( sourceSelectionModel );
other.clearSelection();
}
}
Note that clearing the selection will trigger the listener again, but due to the isSelectionEmpty check you will not end up with a loop. Another approach would be to disable the listener (e.g. with a boolean flag) right before you call clearSelection on the other list.

JTable: double-click should keep prior selection

I have a JTable where I can select one or more cells. I also want to react on double-click for doing some extra action for the selected cells. But the problem is, when the user double-clicks, the selection changes to the clicked cell. But I want to keep the prior selection on double-click, so I can handle the double-click for all selected cells.
EDIT:
Related to this question:
Java : ignore single click on double click?
But I hope, there is a better/easier solution for my case.
The problem is, that on the first click the first event goes out. A bit later the second click might come or not. So the first click event does know nothing. As in the proposed solution a timer might do.
What also might do is on the first click to select nothing, but invoke a special selection event a bit later.
SwingUtilities.invokeLater(myRunnable);
and on handling the double click/myRunnable the true selection. Timing might be unavoidable though.
you can use setClickCountToStart() for XxxCellEditor, I don't know something about your JTable

Java Swing Threading Problem

so here's the problem. I have a JDialog box that consists of 3 combo boxes, a text field, a few buttons and a JTable. The JTable information is filtered based on the text field and combo boxes, so for instance it starts with all of the data and gets shrunk down to only the data that starts with any string value the user decides.
What's happening though is that while the values filter correctly, if I click in the JTable (in the white space, where there are no rows) then the rows that were deleted show up, like they were invisible until I clicked on them. I've tried almost everything:
I've tried re-creating the table every time filter is clicked (bad hack that didn't even work), I've called all of the repaint, revalidate, firechanged methods, I rewrote the dialog from scratch to make sure I didn't do any stupid mistakes (if I made one I didn't find it at least), and I've tried putting them on separate threads. The only fix I haven't tried is using a swing worker, but that's because my filtering was a little too complicated for me to figure out what goes where and how to extend the swing worker correctly. The GUI is generated by netbeans (bleh), and has worked in my other dozen or so JDialogs just fine (perfectly in fact). Here's the method that doest the filtering, if any of you can help it would be greatly appreciated.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
nameFilter = "task1";
javax.swing.table.DefaultTableModel dm = (javax.swing.table.DefaultTableModel)jTable1.getModel();
tempParameters = parameters;
String currentString;
int rowNumber = 0;
while (dm.getRowCount()>rowNumber){
currentString = (String)(jTable1.getValueAt(rowNumber,1));
if(!nameFilter.equalsIgnoreCase(currentString.substring(0,nameFilter.length()))){
dm.removeRow(rowNumber);
parameters--;
}
else rowNumber++;
}
parameters = numOfRows;
}
Update, I also implemented the filter from the comment below, and while it filtered out the correct data, it had the exact same problem. In the future I will probably use this filter feature though, so thanks.
Another update, the code is still failing even after removing everything but this chunk, and all (at least I believe..) I am doing here is doing a simple remove row call. Hope this helps a bit.
Have you tried creating a new Model every time you want to filter, instead of clearing it by deleting rows? Create new model, copy relevant rows to new Model, set new Model in table. Really shouldn't be necessary, but it might be a quick fix.
Also, I really have to wonder why you're calling toLowerCase on two strings when you're using equalsIgnoreCase to compare them.
So long as this method is called from the EDT I don't think there would be a threading problem. Try using
SwingUtilties.isEventDispatchThread()
to make sure.
If you look at the API for DefaultTableModel, updates are being sent to your JTable which will repaint itself, so I don't think that is the problem.
I would guess that it is a logic problem. If you can extract the logic into separate methods it will be easier to test and verify whether it is updating the model as you expect.
Couple of observations:
If the filter happens to be larger than the string content of the row, it'll throw in the substring call
Calling the dm.removerow is generating a bunch of tablerowsdeleted events.
You're asking for a rowcount from the model, yet are getting the value through the table (a little inconsistent, if the model gets wrapped around another model you might be acting upon different rows), so instead of jtable1.getvalueat, use the dm.getvalueat.
I think what might be happening is that as the events get fired I see there are repaint and revalidate events fired in the JTable, these can be trampling over each other as they get enqueued in the EDT.
What I would suggest is to create a new datamodel, add the rows that you want to keep, and then reassign it to your jTable1.setModel(newDm);
Also to watch for is if someone else is modifying the model while you're in your eventlistener.
Hope this helps

Categories