Ik wil naast m'n swing gui een thread laten draaien die mijn GUI moet benaderen zonder dat de hele boel bevriest.
Nu heb ik in andere topics gelezen dat de combinatie van swing en threads toch lastig is. Ik zal mijn thread aan de event-dispatcher moeten toevoegen met behulp van SwingUtilities.invokeLater(Runnable job), maar ik kom er niet helemaal uit.
Ik heb het volgende gebouwd:
In een JPanel heb ik instanties aangemaakt van een JobGenerator (subclass van Thread) en een JList. De JobGenerator genereert at random een nieuwe Job, die in de JList moet worden laten zien. De model van de JList bevat dus een lijst van Job objecten die de Runnable interface implementeren.
Vanaf een abstractAction kan ik de JobGenerator starten, en het is de bedoeling dat de Job's in de listmodel worden geplaatst, en dus ook in de JList worden laten zien.
Wat er dus gebeurt is dat wanneer ik de abstractaction aanroep, de GUI een tijdje bevriest, en als de JobGenerator thread klaar is, dat dan pas de GUI wordt gerefresht.
Ik weet dat ik deze thread in de event dispatcher moet plaatsen, maar ik ben hier verder compleet vast gelopen. Is er iemand die mij op weg kan helpen?
Nu heb ik in andere topics gelezen dat de combinatie van swing en threads toch lastig is. Ik zal mijn thread aan de event-dispatcher moeten toevoegen met behulp van SwingUtilities.invokeLater(Runnable job), maar ik kom er niet helemaal uit.
Ik heb het volgende gebouwd:
In een JPanel heb ik instanties aangemaakt van een JobGenerator (subclass van Thread) en een JList. De JobGenerator genereert at random een nieuwe Job, die in de JList moet worden laten zien. De model van de JList bevat dus een lijst van Job objecten die de Runnable interface implementeren.
Vanaf een abstractAction kan ik de JobGenerator starten, en het is de bedoeling dat de Job's in de listmodel worden geplaatst, en dus ook in de JList worden laten zien.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| public class JobGenerator extends Thread { private List<Job> _jobList; private GeneratorListModel _generatorListModel; public JobGenerator(String filename, GeneratorListModel generatorListModel) throws IOException, InvalidJobInputException { if (filename == null || filename.length() == 0) throw new RuntimeException("Error: filename can't be null or empty"); if (generatorListModel == null) throw new NullPointerException("_generatorListModel can't be null"); _generatorListModel = generatorListModel; init(); fillJobList(filename); } private void init() { _jobList = new LinkedList<Job>(); } private void fillJobList(String filename) throws IOException, InvalidJobInputException { // Lijst wordt gevuld, code niet interessant } public void run() { for (Iterator<Job> itt = _jobList.iterator();itt.hasNext();) { Job job =itt.next(); try { Thread.sleep(job.getTime()); } catch(InterruptedException e) { e.printStackTrace(); } _generatorListModel.enqueue(job); } } } |
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| public class GeneratorListModel implements ListModel { private LinkedList<Job> _jobGeneratorQueue; private List<ListDataListener> _listenerList = new LinkedList<ListDataListener>(); public GeneratorListModel() { _jobGeneratorQueue = new LinkedList<Job>(); } public int getSize() { return _jobGeneratorQueue.size(); } public Object getElementAt(int index) { return _jobGeneratorQueue.get(index); } public void addListDataListener(ListDataListener l) { if (l == null) throw new NullPointerException("l can't be null"); _listenerList.add(l); } public void removeListDataListener(ListDataListener l) { if (l == null) throw new NullPointerException("l can't be null"); _listenerList.remove(l); } public void enqueue(Job job) { if (job == null) throw new NullPointerException("job can't be null"); _jobGeneratorQueue.addLast(job); ListDataEvent e = null; for (Iterator<ListDataListener> itt = _listenerList.iterator();itt.hasNext();) { if (e == null) e = new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, getSize()-1, getSize()-1); itt.next().intervalAdded(e); } } public Job dequeue() { Job job = _jobGeneratorQueue.removeFirst(); ListDataEvent e = null; for (Iterator<ListDataListener> itt = _listenerList.iterator();itt.hasNext();) { if (e == null) e = new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, 0, 0); itt.next().intervalRemoved(e); } return job; } } |
Wat er dus gebeurt is dat wanneer ik de abstractaction aanroep, de GUI een tijdje bevriest, en als de JobGenerator thread klaar is, dat dan pas de GUI wordt gerefresht.
Ik weet dat ik deze thread in de event dispatcher moet plaatsen, maar ik ben hier verder compleet vast gelopen. Is er iemand die mij op weg kan helpen?