I have a LinkedList<JLabel>
and using it on a thread to add or remove them from a JPanel
, the problem is that sometimes the exception happens and the application crashes. In some posts they talk about synchronize my list, others say that I should have an iterator, so I'm a bit confused.
I will add some code for make it easy to understand:
public class MyPanel extends JPanel {
(...)
private LinkedList<JLabel> labels;
(...)
public MyPanel(Color corLabel, Color back, Font text) {
(...)
labels = new LinkedList<>();
(...)
}
this is where the Linked List get initialized now i have 1 method and 1 thread using it:
public void addMensagem(MensagemParaEcra msg) {
JLabel lbl = new JLabel();
lbl.setText(("- " + msg.getTexto() + " -"));
lbl.setForeground(color);
lbl.setFont(textFont);
lbl.setOpaque(true);
lbl.setBackground(backg);
labels.add(lbl);
MyPanel.this.add(lbl);
}
this one just configure the label and add it to the panel and to the linked list
private void start() {
final Runnable running = new Runnable() {
@Override
public void run() {
MyPanel.this.repaint();
}
};
Thread t = new Thread() {
public void run() {
while (true) {
// for each label
for (JLabel lb : labels) {
if (lb.getLocation().x + lb.getWidth() < 0) {
if (msgsRemover.isEmpty() == true) {
//remove the label if she is out of the monitor
MyPanel.this.remove(lb);
// and add the label
MyPanel.this.add(lb);
MyPanel.this.repaint();
MyPanel.this.validate();
} else {
// if there is some message to remove
for (String s : msgsRemover) {
if (lb.getText().toString().equals(s)) {
// remove the visual label
MyPanel.this.remove(lb);
MyPanel.this.repaint();
// remove the message that need to be removed from the linked list
msgsRemover.remove(s);
// remove the label from the JLabel list
labels.remove(lb);
} else {
// if there is no message to be removed, they will just continue
// going to the end of the queue
MyPanel.this.remove(lb);
MyPanel.this.add(lb);
MyPanel.this.repaint();
MyPanel.this.validate();
}
}
}
}
lb.setLocation(lb.getLocation().x - 3, 0);
}
repaint();
try {
SwingUtilities.invokeAndWait(running);
sleep(30);
} catch (InterruptedException ex) {
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
t.start();
}
This is the code where I got the error, sometimes the program crashes and for what it says the problem is on:
for (JLabel lb : labels)
The stacktrace:
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:953)
at java.util.LinkedList$ListItr.next(LinkedList.java:886)
at smstest.MyPanel$3.run(MyPanel.java:110)
So, i used an iterator and it's working, but now i face another problem... there is the code:
for(Iterator<String> it2 = msgsRemover.iterator(); it.hasNext();){
String s = it2.next();
if (lb.getText().toString().equals(s)) {
// remove the visual label
MyPanel.this.remove(lb);
MyPanel.this.repaint();
// remove the message that need to be removed from the linked list
it2.remove();
// remove the label from the JLabel list
it.remove();
so, now my problem is in String s = it2.next(); The stacktrace is:
Exception in thread "Thread-2" java.util.NoSuchElementException
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at smstest.MyPanel$3.run(MyPanel.java:131)
Any clue how can i solve it? Thank you in advance