I'm trying to display a list of items and, when the user clicks on an item, to clear the list and display another list.
If I run this and click on the first entry on the displayed list, the program dies with a long trail of runtime exceptions. If I remove the clear() line (commented below), it runs fine. Adding try/catch didn't reveal any information useful to me. Apologies for the long code, but I couldn't figure out how to shorten and still generate the errors.
What at I doing wrong?
import java.util.*;
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
class ListGui extends JPanel implements ListSelectionListener {
private static JList list;
private static DefaultListModel listModel = new DefaultListModel();
public ListGui() {
super(new BorderLayout());
list = new JList(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(this);
JScrollPane listScrollPane = new JScrollPane(list);
add(listScrollPane, BorderLayout.CENTER);
}
public static void Populate(List<String> lines) {
listModel.clear();
for(String line : lines) {
listModel.addElement(line);
}
}
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
List<String> out = new ArrayList<String>();
out.add("three");
out.add("four");
Populate(out);
}
}
}
public class TestClear {
static JComponent newContentPane = new ListGui();
private static void createAndShowGUI() {
JFrame frame = new JFrame("toast");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
List<String> out = new ArrayList<String>();
createAndShowGUI();
out.add("one");
out.add("two");
ListGui.Populate(out);
}
}
I'm trying to display a list of items and, when the user clicks on an item, to clear the list and display another list.
That doesn't sound like the best design to me. The selection will change whenever you click on an item or when you use the arrow keys to move up or down the list. I'm sure for users that like to use the keyboard you don't want the list to change every time you use an arrow key.
The normal design would be to invoke an Action on the list on a "double click" or when the user users "Enter" from the keboard. This is easily implemente using the List Action concept.
However, if you really do want to update the list on every selection then I would use code like:
list.removeListSelectionListener( this );
populate(...);
list.addListSelectionListener(this);
The problem is that you are calling Populate() in valueChanged() which triggers valueChanged() and hence the stackoverflow.
The simplest solution is to have a flag to prevent reentry.
boolean busy = false;
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false && !busy) {
busy = true;
List<String> out = new ArrayList<String>();
out.add("three");
out.add("four");
Populate(out);
busy = false;
}
}
If your code could be accessed by multiple threads, you should be looking into ReentrantLock
Related
I'm working with drag-and-drop. The user has to drag something from a list to somewhere else. However, the list will move when receiving a ListSelectionEvent, so when the user changes selection, he may unexpectedly perform a drag-and-drop.
My code:
import java.awt.*;
import javax.swing.*;
class Main {
public static void createGUI() {
JFrame f = new JFrame();
JList<String> list = new JList<>(new String[] { "Text A", "Text B" });
list.setFont(list.getFont().deriveFont(24f));
list.setDragEnabled(true);
// list.setTransferHandler(new TransferHandler() { /* ... */ });
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(e -> f.setLocation(f.getX(),
f.getY() + f.getHeight()));
list.setSelectedIndex(0);
f.add(list, BorderLayout.CENTER);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
f.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(Main::createGUI);
}
}
To reproduce, launch this application, put it above some application that accepts a drop (e.g. Eclipse, Notepad++) and toggle the selection several times.
I'm using Windows 7 and JDK 1.8.0_5.
I tried but I couldn't find a work-around. How can I fix this issue?
[Not really related] This is my real application: (including the green cross icon)
Okay I think I understand your problem: You want to have DnD enabled, just not when the user is changing their selection. You should try this (in Java 7, I'm not too comfortable with lambda expressions yet, so I'm still not using Java 8. It'll work on Java 8 though):
class Main {
private static boolean listChanging = false;
public static void createGUI() {
final JFrame f = new JFrame();
JList<String> list = new JList<String>(new String[] { "Text A", "Text B" });
list.setFont(list.getFont().deriveFont(24f));
list.setDragEnabled(true);
list.setTransferHandler(new TransferHandler() {
private static final long serialVersionUID = 1L;
#Override
public int getSourceActions(JComponent c) {
if (listChanging) {
listChanging = false;
return NONE;
} else {
return COPY;
}
}
#Override
#SuppressWarnings("unchecked")
public Transferable createTransferable(JComponent c) {
return new StringSelection(((JList<String>) c).getSelectedValue());
}
});
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
f.setLocation(f.getX(), f.getY() + f.getHeight());
listChanging = true;
}
});
list.setSelectedIndex(0);
f.add(list, BorderLayout.CENTER);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationByPlatform(true);
f.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Main.createGUI();
}
});
}
}
What this code does is that when the user when the user changes selection it set a variable listChanging to true. The when the user drags (by accident or on purpose), it checks if listChanging is true, which means that this was probably an unexpected drag. If the list was not changing, then it allows COPY drags.
Basically, if the drag was during a list change, it disables DnD. If the list did not change, and the user purposefully dragged it enables DnD.
Hope this meets all your needs :)
Still It's not clear what you want to do with your application..
Drag and Drop performs with mouse/key events or you may trigger it through another events.
Here as I can see, it could be in this way that either you can select some of the components from List and perform DnD to transfer that component to another Container.
Please elaborate your question and ask specifically what exactly you want to perform with your sample application.
I have a JList and want to change the tooltips, depending on the entry the mouse hovers over. I tried searching my problem on google, but had no success.
Basically i need to get the object i am currently hovering over.
Every help is appreciated
In order to do that, you have to extend JList and expose the tooltip text method. Here is an example program I found sometime ago using Google:
import java.awt.EventQueue;
import java.awt.event.*;
import javax.swing.*;
// Custom class to extend our JList and expose tooltip functionality.
class MyList extends JList {
public MyList() {
super();
// Attach a mouse motion adapter to let us know the mouse is over an item and to show the tip.
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
MyList theList = (MyList) e.getSource();
ListModel model = theList.getModel();
int index = theList.locationToIndex(e.getPoint());
if (index > -1) {
theList.setToolTipText(null);
String text = (String) model.getElementAt(index);
theList.setToolTipText(text);
}
}
});
}
// Expose the getToolTipText event of our JList
public String getToolTipText(MouseEvent e) {
return super.getToolTipText();
}
}
public class TestJList extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestJList myTest = new TestJList();
myTest.setTitle("Example JList");
myTest.setSize(300, 300);
myTest.setDefaultCloseOperation(EXIT_ON_CLOSE);
MyList list = new MyList();
// Create our model and add some items.
DefaultListModel model = new DefaultListModel();
model.addElement("one");
model.addElement("two");
model.addElement("three");
model.addElement("four");
// Set the model for our list
list.setModel(model);
ToolTipManager.sharedInstance().registerComponent(list);
// Add our custom list and show the form.
MyTest.add(list);
MyTest.setVisible(true);
}
});
}
}
Hope this helps.
1) Assign a MouseListener to all elements in question.
2) Implement the mouseEntered method
3) Inside that method, use event.getSource() to get the element that was hovered.
I have a JDialog dlg, created by a JFrame frm, that contains a JList list.
When I modify the list (through the ListModel), the list itself is repainted but not the JDialog.
This means that, if I delete a line, the list remains with an empty line while if I add a line, this new line won't be shown (because there is no space in the dialog) until I manually force repainting of dlg (doubleclicking in frm).
Following advices in this post :
How to make repaint for JDialog in Swing?
and in this post:
Force repaint after button click
I tried to call, from my controller class (which is where updates to list are made), the following line:
SwingUtilities.getWindowAncestor(dlg).repaint();
but it didn't work.
I also tried:
dlg.repaint();
No luck either...
Any clue?
Thank you very much.
EDIT:
The organization of my classes is as follows:
a controller class that contains a reference to the main JFrame, frm.
I also extended JDialog into MyDialog, which contains a JList.
When a doubleclick on frm is detected, I show the instance of MyDialog (or create, if it is the first time I show it) and the JList is filled with the data passed to the DefaultListModel. MyDialog is painted so that the list has only the space that it needs.
Now, when a specific event is detected by the controller, I get the specific MyDialog, get the ListModel from JList and update it. Here the JList is indeed updated, but Dialog remains the same.
I use a code like this:
MyDialog dlg = group.getDlg();
if(dlg != null){
DefaultListModel listModel = ((DefaultListModel) dlg.getMyJList().getModel());
listModel.addElement(idStock);
SwingUtilities.getWindowAncestor(dlg).repaint();
}
This doesn't repaint dlg.
I also tried:
SwingUtilities.getWindowAncestor(dlg.getMyJList()).repaint();
but it doesn't work.
I checked with the debugger that the lines are actually executed.
I don't have much more code to show, really.....
I think that you going wrong way, define DefaultListModel that accesible throught all Java methods and Classes, this Model would holds your Objects, then put JList to the JDialog or JOptionPane, for example
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
// based on #trashgod code
/** #see http://stackoverflow.com/questions/5759131 */
// http://stackoverflow.com/questions/8667719/jdialog-repaint-after-jlist-modification
public class ListDialog {
private static final int N = 12;
private JDialog dlg = new JDialog();
private DefaultListModel model = new DefaultListModel();
private JList list = new JList(model);
private JScrollPane sp = new JScrollPane(list);
private int count;
public ListDialog() {
list.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
JPanel panel = new JPanel();
panel.add(new JButton(new AbstractAction("Add") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
append();
if (count <= N) {
list.setVisibleRowCount(count);
dlg.pack();
}
}
}));
panel.add(new JButton(new AbstractAction("Remove") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
int itemNo = list.getSelectedIndex();
if (itemNo > -1) {
removeActionPerformed(e, itemNo);
}
}
}));
for (int i = 0; i < N - 2; i++) {
this.append();
}
list.setVisibleRowCount(N - 2);
dlg.add(sp, BorderLayout.CENTER);
dlg.add(panel, BorderLayout.SOUTH);
dlg.pack();
dlg.setLocationRelativeTo(null);
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setVisible(true);
}
private void removeActionPerformed(ActionEvent e, int itemNo) {
System.out.println("made_list's model: " + list.getModel());
System.out.println("Model from a fresh JList: " + new JList().getModel());
model = (DefaultListModel) list.getModel();
if (model.size() > 0) {
if (itemNo > -1) {
model.remove(itemNo);
}
}
}
private void append() {
model.addElement("String " + String.valueOf(++count));
list.ensureIndexIsVisible(count - 1);
}
public static void main(String[] a_args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ListDialog pd = new ListDialog();
}
});
}
}
My Swing GUI displays a JList of items that are being sequentially removed by a background thread.
Behind the JList is an ArrayDeque<Card>, myHopper, implementing myHopper.getSize() and myHopper.getElementAt(), as per the contract of an AbstractListModel.
The background thread removes items using myHopper.poll().
Not surprisingly, I'm getting AWT array index out of bounds exceptions currently.
What should I be doing to properly synchronize access to myList between the EDT thread and my background thread? I have seen references to Collections.synchronizedList(arrayList) but I don't think that fits my ArrayDeque.
Have you tried just using a LinkedBlockingDeque instead of the ArrayDeque?
The short answer to my question appears to be "You can't: you must never attempt to access a Swing component [and that includes its model] from any thread other than the EDT."
This post shows how I eventually solved the problem. A worker thread needs to pull an item from a JList's model, and does so using invokeAndWait() to schedule that work on the EDT, and then waits until that task is done, and then continues.
Using the synchronized LinkedBlockingDeque didn't work, and I suspect that it's because the EDT makes a nonatomic series of calls to the Deque interface when updating the GUI component. Any change to the model between calls, by another thread, could destroy any assumptions of stability that the EDT is making.
(Perhaps that's what's being hinted at by the persistent "Warning: Swing is not thread safe" that appears throughout the Swing documentation.)
The following code works well for me, and might give you some ideas.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.Timer;
public class JListDemo {
public static void main(String[] args) {
final MyListModel model = new MyListModel();
// set up a background task to periodically purge items from the list
java.util.Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
String item = model.poll();
if (item != null) {
System.out.println("Removed " + item + " from list");
} else {
System.out.println("Nothing to remove off list, click 'Add Item' button to add more");
}
}
}, 1000, 2000);
JList list = new JList(model);
// Add a button to add new items to the list
JButton button = new JButton("Add Item");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.offer(new Date().toString());
}
});
JFrame frame = new JFrame("JList Demo");
frame.add(list);
frame.add(button, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
private static class MyListModel extends DefaultListModel {
private final ArrayDeque<String> dq = new ArrayDeque<String>();
public synchronized String poll() {
String head = dq.poll();
if (head != null) {
removeElementAt(0);
}
return head;
}
public synchronized void offer(String item) {
dq.offer(item);
insertElementAt(item, getSize());
System.out.println("Added " + item + " to list");
}
}
}
Execute your operations using SwingWorker instead.
http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
I need your suggestions and guidence on following task.
I have a frame which has two JComboBoxes supposed they are named combo1 and combo2, a JTable and other components.
At initial stage when frame is visible with above component. The combo1 combobox is filled with some values but no value is selected at initial stage, the combo2 combobox is disabled and the table is empty.
I have added an actionListener on combo1 as well as combo2. There are two types of values in combo1 suppose those values are type1 and type2.
Condition 1:
When we selects value type1 from Combo1 the actionListener method is called of combo1 which invokes a method which combo2 remains disabled and adds some rows to table related to selected value type1 from combo1.
Condition 2:
when we selects value type2 from combo1 the actionListener method is called of combo1 which invokes a method who makes combo2 filled with some values related to type2 and gets enabled but no value is selected from combo2 and table also should remain empty until we selects any value from combo2.
table at every addition of value to combo2 the action listener method of combo2 is gets fired. In actionListener method of combo2 which gets combo2 selected value but here there is no selected value of combo2 which leads to a NullPointerException.
So what should I do that the action listner method of combo2 will not be get executed after addition of an values to combo2.
You could remove the action listener before you add the new elements, and add it back once you're done . Swing is single threaded so there is no need to worry about other threads needing to fire the listener.
Your listener could probably also check if something is selected and take appropriate action if not. Better than getting a NPE.
What i do instead of adding and removing action listeners i have a boolean variable in my action listeners that is true if it has to allow the action through or false if it has to block it.
I then set it to false when i do some changes that will fire off the action listener
JComboBox test = new JComboBox();
test.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(testActionListenerActive)
{
//runn your stuff here
}
}
});
//then when i want to update something where i want to ignore all action evetns:
testActionListenerActive = false;
//do stuff here like add
SwingUtilities.invokeLater(() -> testActionListenerActive = false);
//and now it is back enabled again
//The reason behind the invoke later is so that if any event was popped onto the awt queue
//it will not be processed and only events that where inserted after the enable
//event will get processed.
try this:
indicatorComboBox = new JComboBox() {
/**
* Do not fire if set by program.
*/
protected void fireActionEvent() {
// if the mouse made the selection -> the comboBox has focus
if(this.hasFocus())
super.fireActionEvent();
}
};
although its late, a better alternative would be to disabled the combobox to be modified prior to being modified. by doing so, you prevent firing events of the modified combobox, when for example, you use methods likes removeAllItems() or addItem()
String orderByOptions[] = {"smallest","highest","longest"};
JComboBox<String> jcomboBox_orderByOption1 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption2 = new JComboBox<String(orderByOptions);
JComboBox<String> jcomboBox_orderByOption3 = new JComboBox<String(orderByOptions);
jcomboBox_orderByOption1.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent itemEvent)
{
int eventID = itemEvent.getStateChange();
if (eventID == ItemEvent.SELECTED)
{
Object selectedItem = jcomboBox_orderByOption1.getSelectedItem();
jcomboBox_orderByOption2.setEnabled(false);
jcomboBox_orderByOption2.removeAllItems();
for (String item: string_orderByOptions)
{
if (!item.equals(selectedItem))
{
jcomboBox_orderByOption2.addItem(item);
}
}
jcomboBox_orderByOption2.setEnabled(true);
}
}
});
jcomboBox_orderByOption2.addItemListener(new ItemListener()
{
public void itemStateChanged(ItemEvent itemEvent)
{
int eventID = itemEvent.getStateChange();
if (eventID == ItemEvent.SELECTED)
{
Object selectedItem1 = jcomboBox_orderByOption1.getSelectedItem();
Object selectedItem2 = jcomboBox_orderByOption2.getSelectedItem();
jcomboBox_orderByOption3.setEnabled(false);
jcomboBox_orderByOption3.removeAllItems();
for (String item: string_orderByOptions)
{
if (!item.equals(selectedItem1) && !item.equals(selectedItem2))
{
jcomboBox_orderByOption3.addItem(item);
}
}
jcomboBox_orderByOption3.setEnabled(true);
}
}
});
The cleaner way is to use lambda expressions like this:
do(comboBox, () -> comboBox.setSelectedItem("Item Name"));
For the above to work, you need the following method defined somewhere:
public static void do(final JComboBox<String> component, final Runnable f) {
final ActionListener[] actionListeners = component.getActionListeners();
for (final ActionListener listener : actionListeners)
component.removeActionListener(listener);
try {
f.run();
} finally {
for (final ActionListener listener : actionListeners)
component.addActionListener(listener);
}
}
This works:
/** Implements a Combo Box with special setters to set selected item or
* index without firing action listener. */
public class MyComboBox extends JComboBox {
/** Constructs a ComboBox for the given array of items. */
public MyComboBox(String[] items) {
super(items);
}
/** Flag indicating that item was set by program. */
private boolean isSetByProgram;
/** Do not fire if set by program. */
protected void fireActionEvent() {
if (isSetByProgram)
return;
super.fireActionEvent();
}
/** Sets selected Object item without firing Action Event. */
public void setSelection(Object item) {
isSetByProgram = true;
setSelectedItem(item);
isSetByProgram = false;
}
/** Sets selected index without firing Action Event. */
public void setSelection(int index) {
isSetByProgram = true;
setSelectedIndex(index);
isSetByProgram = false;
}
}
Note: You can't just override setSelectedItem(...) or setSelectedIndex(...) because these are also used internally when items are actually selected by user keyboard or mouse actions, when you do not want to inhibit firing the listeners.
To determine whether or not to perform various methods in actionListener interface methods (actionPerformed() blocks of code) use setActionCommand() on source components (combo1 or combo2).
For your example, before adding elements to combo2, call setActionCommand("doNothing") and guard your comboBoxActionPerformed() method.
Here's a compilable example that uses this principle to have one combo set another combo's selected index while also displaying a String in a JTextField. By using setActionCommand() and guarding the comboActionPerformed() block of code, the JTextField will cycle through each word in the wordBank. If the comboActionPerformed() method was not guarded or if the actionCommand String was not changed, 2 actionEvents will trigger and the textField will skip words.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
/** #author PianoKiddo */
public class CoolCombos extends JPanel {
JComboBox<String> candyCombo;
JComboBox<String> flavorCombo;
JTextField field;
String[] wordBank;
int i = 0;
CoolCombos() {
super();
initComponents();
addComponentsToPanel();
}
private void initComponents() {
initCombos();
initTextField();
}
private void initCombos() {
ActionListener comboListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
comboActionPerformed(e);
}
};
String[] candyList = {"Sourpatch", "Skittles"};
String[] flavorList = {"Watermelon", "Original"};
candyCombo = new JComboBox<>(candyList);
candyCombo.addActionListener(comboListener);
flavorCombo = new JComboBox<>(flavorList);
flavorCombo.addActionListener(comboListener);
}
private void initTextField() {
wordBank = new String[]{"Which", "Do", "You", "Like", "Better?"};
field = new JTextField("xxxxx");
field.setEditable(false);
field.setText(wordBank[i]);
}
private void addComponentsToPanel() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.add(candyCombo);
this.add(flavorCombo);
this.add(field);
}
public void comboActionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (!command.equals("doNothing")) {
JComboBox combo = (JComboBox) e.getSource();
if (combo.equals(candyCombo)) {
setOtherComboIndex(candyCombo, flavorCombo); }
else {
setOtherComboIndex(flavorCombo, candyCombo); }
displayText(); //replace here for toDo() code
}
}
private void setOtherComboIndex(JComboBox combo, JComboBox otherCombo) {
String command = otherCombo.getActionCommand();
otherCombo.setActionCommand("doNothing"); //comment this line to skip words.
otherCombo.setSelectedIndex(combo.getSelectedIndex());
otherCombo.setActionCommand(command);
}
private void displayText() {
i++;
String word;
if (i > 4) { i = 0; }
word = wordBank[i];
field.setText(word);
this.repaint();
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CoolCombos");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new CoolCombos();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setMinimumSize(frame.getSize());
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
I kind of went the stupid simple route with this issue for my program since I am new to programming.
I changed the action listeners to have a counter if statement:
if(stopActionlistenersFromFiringOnLoad != 0){//action performed ;}
Then at the end of the java program creation, I added 1 to the counter:
topActionlistenersFromFiringOnLoad += 1;
To avoid that addItem method fire events is better to use an DefaultComboBoxModel in the JComboBox to add data. Also, if you invoke a model.addElement(), an event is fired, so, you can add all the elements to the model and later use JComboBox.setModel(model). In this way, if you add elements to the model, events are not fired because you have not link the JComboBox with the model. Then, I show you an example.
private void rellenarArrendatarioComboBox(ArrayList<Arrendatario> arrendatarios) {
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(new Arrendatario(" -- Seleccione un arrendatario --"));
for (Arrendatario arrendatario : arrendatarios) {
model.addElement(arrendatario);
}
ArrendatarioComboBox.setModel(model);
}
First, we create the model, add all elements to the model (events are not fired because you have not link the JComboBox with the model), we link the model with the JComboBox using ArrendatarioComboBox.setModel(model). After linking, events are fired.