Jason S
Jason S

Reputation: 189676

jgoodies bindings + coalescing frequent changes

I have a java app that updates data at a variable rate (received from a fairly high-speed data stream out of my control, but up to 120Kbytes/sec), and I would like to display statistics like the # of bytes/packets received, using a dialog box.

I'm looking into JGoodies bindings and got something preliminarily working with artificial data received at low rates.

What I would like to do, roughly, is:

  1. make a bean class something like this:

    public class Statistics
    {
      private int bytes;
      private int goodPackets;
      private int badPackets;
      private int totalPackets;
    
      public int getBytes() { return bytes; }
      public int getGoodPackets() { return goodPackets; }
      public int getBadPackets() { return badPackets; }
      public int getTotalPackets() { return totalPackets; }
    
      public void update(/* TBD */) { /* updates the fields appropriately */ }
      public Statistics() { bytes=goodPackets=badPackets=totalPackets=0; }
    }
    
    Statistics stats;
    
  2. bind the 4 fields to elements in my GUI

  3. be able to call stats.update() at whatever speed is necessary in my main application thread, where the call to "update" is what triggers the GUI's change listeners
  4. have the GUI "automatically" update at a lower rate that I can specify, approximately 5-20Hz, so it doesn't get overwhelmed with gobs of triggered events.

Is there an appropriate mechanism that would let me do what I want? I'm looking at JGoodies DelayedReadValueModel but I don't really get how to use it.

If I had to do it myself manually, I guess what I'd probably do is:

  1. have a mirrored copy of Statistics, and add some kind of update flag, as well as a link from the original to the mirrored copy, and a timer timeout
  2. when the update() method is called, set the update flag, and call a method like maybePropagate()
  3. maybePropagate(): if the timer timeout is in progress, or the link to the mirrored copy is null, it does nothing; otherwise it starts the timeout and sends the updated data to the mirrored copy, and clears the update flag
  4. when the timer timeout expires, if the update flag is set and the link to the mirrored copy is non-null, it sends the updated data to the mirrored copy and clears the update flag
  5. Having implemented the previous 4 elements, my mirrored copy has a maximum rate which it gets updated, and therefore I can just bind the GUI elements to the fields of the mirrored copy with the regular JGoodies BeanAdapter.

Any suggestions?

Upvotes: 3

Views: 306

Answers (2)

Karsten Lentzsch
Karsten Lentzsch

Reputation: 191

Although the JGoodies Binding addresses this problem with the Delayed* classes, you may consider using an approach with standard Swing features.

If you use a SwingWorker, you can publish elements in the background and process them in the EDT. The SwingWorker process will get chunks of published data and reduces the number of EDT changes.

Upvotes: 3

Felix Leipold
Felix Leipold

Reputation: 1113

Given you have got a presentation model for your statistics, your binding code might look like this:

ValueModel bytesModel = statsPresentationModel.getModel("bytes");
label = BasicComponentFactory.createLabel(bytesModel);

Now to delay the update you could wrap the value model for the byte field:

ValueModel bytesModel = new DelayedReadValueModel(statsPresentationModel.getModel("bytes"));
label = BasicComponentFactory.createLabel(bytesModel);

Upvotes: 1

Related Questions