[java] AbstractTableModel fireTableChanged werkt niet

Pagina: 1
Acties:

  • PhoneTech
  • Registratie: Mei 2000
  • Laatst online: 08-05 12:31
Ik heb weer eens ruzie met de JTable.

Ik heb een list model die data van de server haalt. Dit zit zelf in een Runnable.
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
private class RecieveLotListThread implements Runnable
    {

        public void run()
        {
            List lotList;
            try
            {

                lotList = management.getLotList();
                int numItems = lotList.size();
                int downloadedItems = 0;

                LotDataModel lotData;

                for (Iterator i = lotList.iterator(); i.hasNext();)
                {
                    LotDTO lot = (LotDTO) i.next();
                    lotData = new LotDataModel(management, lot);
                    lotData.initialize();
                    addOnce(lotData);
                    downloadedItems++;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }


de code om de thread te starten is
Java:
1
2
3
4
5
6
7
8
public void loadData()
    {
        if (receiveLotListThread == null)
            receiveLotListThread = new Thread(new RecieveLotListThread());
        if (!receiveLotListThread.isAlive())
            receiveLotListThread.start();

    }



in de list model staat dan
Java:
1
2
3
4
5
private void addOnce(LotDataModel lot)
    {
        list.addOnce(lot);
        pcs.firePropertyChange(PropertyChangeSupport.EVENT_ADD, 0, list.size());
    }

de EVENT_ADD is een string btw

Daarnaast heb ik een tablemodel gemaakt die een AbstractTableModel extends
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
public LotTableModel(LotListModel listModel)
    {
        this.listModel = listModel;
        this.listModel.addPropertyChangeListener(new AddListModelListener(),
                PropertyChangeSupport.EVENT_ADD);
    }
...
private class AddListModelListener implements PropertyChangeListener
    {
        public void propertyChange(PropertyChangeEvent evt)
        {
            fireTableDataChanged();
            System.out.println(evt);
        }
    }
...


Ik weet dat de events aankomen, maar hij repaint de table niet! ik heb ongeveer alle fireXXXchanged geprobeerd maar snap er effe helemaal nix meer van...

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

PhoneTech schreef op dinsdag 19 april 2005 @ 14:18:
Ik heb weer eens ruzie met de JTable.

Ik heb een list model die data van de server haalt. Dit zit zelf in een Runnable.
Java:
1
private class RecieveLotListThread implements Runnable
Waarom noem jij dit ding een Thread? Het is een Runnable implementatie.. Noem het dan RecieveLotListRunnable/Job/Worker/Task. Thread != Runnable.
de code om de thread te starten is
Java:
1
2
3
4
5
6
7
8
public void loadData()
    {
        if (receiveLotListThread == null)
            receiveLotListThread = new Thread(new RecieveLotListThread());
        if (!receiveLotListThread.isAlive())
            receiveLotListThread.start();

    }
Ik zou dit op een andere manier oplossen. Als je niet wilt dat iets gebeurt terwijl die aan het downloaden is, zou ik een modal dialog opwerpen die verhindert dat er nog iets gedaan kan worden.

Verder ga je niet zo werken met isAlive.
Daarnaast heb ik een tablemodel gemaakt die een AbstractTableModel extends
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
public LotTableModel(LotListModel listModel)
    {
        this.listModel = listModel;
        this.listModel.addPropertyChangeListener(new AddListModelListener(),
                PropertyChangeSupport.EVENT_ADD);
    }
...
private class AddListModelListener implements PropertyChangeListener
    {
        public void propertyChange(PropertyChangeEvent evt)
        {
            fireTableDataChanged();
            System.out.println(evt);
        }
    }
...
Ik krijg door de complexiteit spontaan even hoofdpijn. Ik zie niet hoe de gegevens aan elkaar gerelateerd zijn.

[edit]
Jouw tablemodel luisterd naar de ListModel zie ik nu.
Ik weet dat de events aankomen, maar hij repaint de table niet! ik heb ongeveer alle fireXXXchanged geprobeerd maar snap er effe helemaal nix meer van...
Jouw events komen binnen van een andere thread dan de event dispatching thread (namelijk de thread die alles inlaad). Dit zou een oorzaak van de problemen kunnen zijn.


Opmerking:
Wat is het nut van die ListModel icm die TableModel? Ik snap dat je daarmee een model hebt (de listmodel) waar verschillende objecten naar kunnen luisteren (de tablemodel). Maar heb jij dit probleem in de praktijk? Is het niet veel eenvoudiger om die data gewoon in die TableModel direct te plaatsen zonder die ListModel? Jouw oplossing kan een krachtige oplossing zijn, als je volledig via de ListModel blijft werken. maar als die tablemodel een snapshot is van een tijdelijk moment op de server, dan is het imho onzin om een rekening te betalen (voor abstracties) maar geen voordeel erbij te halen aangezien die er denk ik niet zijn. *weet iets van de opdracht van de TS*

[ Voor 21% gewijzigd door Alarmnummer op 19-04-2005 14:45 ]


  • PhoneTech
  • Registratie: Mei 2000
  • Laatst online: 08-05 12:31
Alarmnummer schreef op dinsdag 19 april 2005 @ 14:33:
[...]

Waarom noem jij dit ding een Thread? Het is een Runnable implementatie.. Noem het dan RecieveLotListRunnable/Job. Thread != Runnable.

[...]

Ik zou dit op een andere manier oplossen. Als je niet wilt dat iets gebeurt terwijl die aan het downloaden is, zou ik een modal dialog opwerpen die verhindert dat er nog iets gedaan kan worden.

Verder ga je niet zo werken met isAlive.
modal dialog vind ik zelf niet zo een geweldige oplossing omdat het onderliggende systeem dan locked. het kan best zijn dat het een tijdje duurt om een lijst te downloaden. En ook al doe ik setModal, dna heb ik nog steeds hetzelfde probleem. De JTable wordt pas goed weergegeven als ik het venster in de desktop pane resize...
[...]

Ik krijg door de complexiteit spontaan even hoofdpijn. Ik zie niet hoe de gegevens aan elkaar gerelateerd zijn.
Welke complexiteit?
[/quote]
[...]

Jouw events komen binnen van een andere thread dan de event dispatching thread (namelijk de thread die alles inlaad). Dit zou een oorzaak van de problemen kunnen zijn.[/quote]

Ik denk ook dat hier het probleem zit, maar google werkt ook niet echt mee, en oplossing daarvoor evenmin...

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

PhoneTech schreef op dinsdag 19 april 2005 @ 14:39:
[...]

modal dialog vind ik zelf niet zo een geweldige oplossing omdat het onderliggende systeem dan locked. het kan best zijn dat het een tijdje duurt om een lijst te downloaden. En ook al doe ik setModal, dna heb ik nog steeds hetzelfde probleem. De JTable wordt pas goed weergegeven als ik het venster in de desktop pane resize...
Dat klopt. Door een Dialog modal en visible te maken, worden events die afkomstig zijn van componenten met een parent != die modal dialog genegeerd.
Welke complexiteit?
Zie mijn edit bij mijn vorige reply.

Ik heb snel even in de firexxx methodes van die abstracttablemodel gekeken, en ik zie niet dat die automatisch op de event dispatching thread worden uitgevoerd. Daarom zou je het zelf kunnen doen:

code:
1
2
3
SwingUtilities.invokeLater(new Runnable(){
     public void run(){tablemodel.fireblabla();)
});

  • PhoneTech
  • Registratie: Mei 2000
  • Laatst online: 08-05 12:31
Alarmnummer schreef op dinsdag 19 april 2005 @ 14:33:
Opmerking:
Wat is het nut van die ListModel icm die TableModel? Ik snap dat je daarmee een model hebt (de listmodel) waar verschillende objecten naar kunnen luisteren (de tablemodel). Maar heb jij dit probleem in de praktijk? Is het niet veel eenvoudiger om die data gewoon in die TableModel direct te plaatsen zonder die ListModel? Jouw oplossing kan een krachtige oplossing zijn, als je volledig via de ListModel blijft werken. maar als die tablemodel een snapshot is van een tijdelijk moment op de server, dan is het imho onzin om een rekening te betalen (voor abstracties) maar geen voordeel erbij te halen aangezien die er denk ik niet zijn. *weet iets van de opdracht van de TS*
De JTable laat idd een soort van snapshot zien van de database. Dit overview is behoorlijk duur. Meerdere objecten op de server moet aaangeschreven worden en al met al duurt het ongeveer 20-30 seconden om een lijst van 240 objecten samen te stellen.

de ListModel extends niet van ListModel. benaming is krom, ga ik nu ook effe fixen (net zoals die andere benamingen)

Het is idd eenvoudiger om de data direct in een tablemodel te gooien, maar zoals ik al zei, het is een behoorlijk dure operatie, en om voor elke view (want er komen er veel, behoorlijk veel) lijtk het mij verstandig om een goede basis list model te hebben die ik in meerdere models kan pluggen. Updates van de server daargelaten. als een object geopend wordt, dan zal hij beslist de meest recente versie ophalen van de server (en deze ook vervolgens locken, maar dat is een ander verhaal).

Ik weet bijna zeker dat de dispatching thread zit te irriteren, en dat de events wel aankomen, maar de dispatching thread er nix mee doet...

PS: Die Thread benaming is een reliek omdat ik eerste een thread had, die vervolgens een inline runnable aansprak...

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

PhoneTech schreef op dinsdag 19 april 2005 @ 14:58:
[...]
Het is idd eenvoudiger om de data direct in een tablemodel te gooien, maar zoals ik al zei, het is een behoorlijk dure operatie, en om voor elke view (want er komen er veel, behoorlijk veel) lijtk het mij verstandig om een goede basis list model te hebben die ik in meerdere models kan pluggen.
Maar een standaar list zal ook voldoen als je wilt cachen. Kan je die list aan iedereen uitdelen die daar behoefte aan heeft.

Ik weet verder niet genoeg van je applicatie om daar een beter antwoord op te kunnen geven. Maar mijn advies is kiss kiss kiss..
Ik weet bijna zeker dat de dispatching thread zit te irriteren, en dat de events wel aankomen, maar de dispatching thread er nix mee doet...
Probeer daarom die SwingUtilities.invoke methodes

[edit]
Nog een ander probleem. Ik weet niet of die AbstractTableModel implementatie threadsafe is, maar als jouw inlaad thread items aan het toevoegen is (eventueel via listeners naar de ListModel) en de event dispatching thread is aan het lezen, dan kunnen er grote problemen ontstaan.

In principe zou je als je veilig wilt zijn, iedere methode op die ListModel die wordt aangesproken door jouw laadthread altijd via een SwingUtilities.invoke... methode moeten laten plaatsvinden. Dan kan je de garantie geven dat er nooit meerdere threads tegelijk mee bezig zijn en dat er daarom geen concurrency problemen kunnen optreden.

[ Voor 27% gewijzigd door Alarmnummer op 19-04-2005 15:07 ]


  • PhoneTech
  • Registratie: Mei 2000
  • Laatst online: 08-05 12:31
[quote]Alarmnummer schreef op dinsdag 19 april 2005 @ 15:03:
[...]

Maar een standaar list zal ook voldoen als je wilt cachen. Kan je die list aan iedereen uitdelen die daar behoefte aan heeft.
[\quote]
ListModel is ook een standaard list, alleen met propertychangesupport :)
Ik weet verder niet genoeg van je applicatie om daar een beter antwoord op te kunnen geven. Maar mijn advies is kiss kiss kiss..
dank je O+

Maar even op het Keep is simple stupid: Ik zou niet weten hoe die makkelijker kan met de requirements die ik heb....
[...]

Probeer daarom die SwingUtilities.invoke methodes


[edit]
Nog een ander probleem. Ik weet niet of die AbstractTableModel implementatie threadsafe is, maar als jouw inlaad thread items aan het toevoegen is (eventueel via listeners naar de ListModel) en de event dispatching thread is aan het lezen, dan kunnen er grote problemen ontstaan.

In principe zou je als je veilig wilt zijn, iedere methode op die ListModel die wordt aangesproken door jouw laadthread altijd via een SwingUtilities.invoke... methode moeten laten plaatsvinden. Dan kan je de garantie geven dat er nooit meerdere threads tegelijk mee bezig zijn en dat er daarom geen concurrency problemen kunnen optreden.
mijn laadthread heeft geen enkele referentie naar visuele componenten. Eerst had ik een JInternal Pane die in de constructor van de laadthread gezet wordt, vervoglens kon ik vanuit de laadthread een mooie JProgressBar manipuleren. Maar dat leek me naderhand niet zo een goed idee, en heb dat er allemaal afgesloopt. De LotListModel (iemadn een tip voor een nieuwe naam?) heeft geen enkele binding met visuele componenten. Componenten worden verwacht naar dit object te luisteren met de PropertyChangeSupport.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

[quote]PhoneTech schreef op dinsdag 19 april 2005 @ 15:14:
Alarmnummer schreef op dinsdag 19 april 2005 @ 15:03:
[...]

Maar een standaar list zal ook voldoen als je wilt cachen. Kan je die list aan iedereen uitdelen die daar behoefte aan heeft.
[\quote]
ListModel is ook een standaard list, alleen met propertychangesupport :)
Ik bedoel dat je dat hele event verstuur aspect moet droppen.
Maar even op het Keep is simple stupid: Ik zou niet weten hoe die makkelijker kan met de requirements die ik heb....
Gewoon een immutable versie aan componenten meegeven als ze behoefte hebben aan data. Zo gauw jij centraal nieuwe data op gaat halen dan gooi je de ref naar de oude lijst weg.. en krijg je centraal weer een ref naar een nieuwe lijst. Wat je dan wilt doen met de componenten die nog een lijst in zich hebben is een 2e... Daar zou je misschien wel iets met een event kunnen doen: Stale Data Event ofzo.
mijn laadthread heeft geen enkele referentie naar visuele componenten.
Dat heeft hij wel.

Als jou laadthread iets gaat laden, dan gooit hij iets in een ListModel. jouw ListModel ontvang dit item en verstuurd een ListCHangeEvent. De TableModel is Listener en ontvangt dit event.. Jouw TableModel verstuurd zelf een event en een van de ontvangers zal de JTable zijn. Jouw JTable krijg dus van jouw loadthread een event binnen...

  • PhoneTech
  • Registratie: Mei 2000
  • Laatst online: 08-05 12:31
Ik ga het event systeem droppen. de datalaadthread stop ik wel in de tablemodel. minder lagen, meer controle..wist door de bomen het bos niet meer te vinden...
Pagina: 1