re: FunctionList + Calculations.sumFloats() behaving unpredictably?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

re: FunctionList + Calculations.sumFloats() behaving unpredictably?

Kevin Day
I think that you might be using the wrong notification to decide when to update your label.
 
Calculations are intended to have a property change listener attached to them (i.e. attached to the calculation).  When you listen to event change notifications on the source list, there is a very good chance that you will recive a change notification *before* the calculation receives it's change notification.
 
The event notification order is:
 
Master --> FunctionList --> Calculation1
           --> FunctionList --> Calculation2
           --> Calculation3
 
in the above, if you are listening for changes on Master, then going and grabbing values from the Calculations, then who knows what values the calculations are going to have!
 
 
Given your code below (more on that in a second), what you'd want to do is create a single ProperyChangeListener and register it with each of your calculations, then have the PCL set the label text.  In other words, listen to the object(s) who's value(s) you are interested in.
 
 
So that will work.  Every change to the master list will fire one PC event.  Then the change will propogate to the first calculation, and it will fire another PC event.  Then the change will propogate to the last calculation, and you'll get another PC event.
 
As you can imagine, this is pretty innefficient.  Also, you are maintaining a whole set of lists for no other reason than to use them in the calculation...
 
If your data set isn't huge, then this approach will work fine.  But a more elegant approach here would be to write your own Calculation object that computes just on the master list.  Have it compute the average and sum and count (you can just take the code from the sunFloats() and sumIntegers() calculations in the GL source), and construct an object that exposes the 3 totals as properties.
 
So the calculation will be a Calculation<Summary> instead of 3 calculations.
 
Then you add a property change listener to the one calculation, and create a string from the Summary, then set the label text (on the EDT!).
 
This may sound daunting, but it's really not.  If you start with the source for the calculation that comptuers sumFloats(), you should be able to adapt it pretty easily.
 
 
 
If I were doing this, I'd probably use a binding framework like BBB and XProperty to bind the Summary object to the label text, but that's a small implementation detail just to make the code cleaner.  For what you are doing, a quick and dirty PropertyChangeListener is probably all that's needed.
 
Does that help?
 
- K
 
----------------------- Original Message -----------------------
  
From: Clayton Carter [hidden email]
To: users [hidden email]
Cc: 
Date: Thu, 25 Feb 2010 23:26:43 -0500
Subject: FunctionList + Calculations.sumFloats() behaving unpredictably?
  
I'm really confusing myself with some GL Calculations.  Same old
story: I have a JTable to display a filtered and sorted list of
objects.  That part is working fine as far as I can tell.  But I want
to include a small status message that tells the user how many rows
are displayed and a handful of other brief stats.  For whatever
reason, this is being done with a single JLabel whose text is a
composite of several stats.  (Imagine the Label reading: "Count: 8 /
Sum: 60 / Average: 7.5" or something.)  For this reason,
SwingCalculations.bind() doesn't work for me.

Anyway, I create several FunctionLists -  one for each statistic - and
use an anonymous FunctionList.Function to just select out the
properties/column values that will be calculated.  I do this as
follows:

FunctionList intList =
             new FunctionList<CPSRecord, Integer>( masterListFiltered,
                                                new
FunctionList.Function<CPSRecord, Integer>() {
                                                   public Integer
evaluate( CPSRecord p ) {
                                                      return (
(CPSSubRecord) p ).getInt();
                                                   }} );

FunctionList floatList =
             new FunctionList<CPSRecord, Float>( masterListFiltered,
                                                 new
FunctionList.Function<CPSRecord, Float>() {
                                                    public Float
evaluate( CPSRecord p ) {
                                                       return (
(CPSSubRecord) p ).getFloat();
                                                    }} );


I then generate the Calculations as such:

summaryCount = Calculations.count( masterListFiltered );
summarySumInt = Calculations.sumIntegers( intList );
summarySumFloat = Calculations.sumFloats( floatList );


I then add "this" as a listener so that I can reset my Label when the
list(s) are updated.

masterListFiltered.addListEventListener( this );

My listChanged() method simply fires off a call to updateLabel(),
which more or less just does:

lblStats.setText( buildStatString() );

and buildStatString() is itself very simple:

      String s = "";

      if ( summaryCount != null && summaryCount.getValue() > 0 ) {
          s += "Count:" + summaryCount.getValue();

          String temp = summarySumInt.getValue().toString();
          if ( ! temp.equals("") )
              s += "/SumInt:" + temp;

          t = summarySumFloat.getValue().toString();
          if ( ! t.equals("") )
              s += "/SumFloat:" + t;
      }

      return s;


OK, now to explain the unpredictable behavior.  Whenever the list is
changed (if I change the filter, for example), the statistics are
updated and the **count and sumInts are always correct**, but the
sumFloats seem to reflect what the value was just before the list
changed.

It's hard to find much of a pattern in the results.  Sometimes the
stats change when I unfocus and refocus the filter text box, but in
those labels then reflect neither the value from the currently
displayed list nor from the previously displayed list.

Anything sound familiar, because I fear I'm in over my head.  I'm
porting a fairly complex app to GlazedLists and have been really
impressed by what they offer, but I'm often finding myself confused by
some of their interactions.

Thanks for any help you can offer.

Clayton

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


--------------------------------------------------------------------- To unsubscribe, e-mail: [hidden email] For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: FunctionList + Calculations.sumFloats() behaving unpredictably?

Clayton Carter-2
May I revive a positively crusty old thread?  I was having a problem
with a piece of code and searched for some help ... only to find that
I had asked for help with the same problem pretty much exactly 2 years
ago.

So, Kevin, if you're still out there, yes this information helped me.
For the time being, I simply reordered the way my lists and
Calculations are created and bound so that the update happens when it
should.  But I see the wisdom and have added it to my list, to write
my own Calculation.

Thank you,
Clayton


On Fri, Feb 26, 2010 at 12:26 AM, Kevin Day <[hidden email]> wrote:

> I think that you might be using the wrong notification to decide when to
> update your label.
>
> Calculations are intended to have a property change listener attached to
> them (i.e. attached to the calculation).  When you listen to event change
> notifications on the source list, there is a very good chance that you will
> recive a change notification *before* the calculation receives it's change
> notification.
>
> The event notification order is:
>
> Master --> FunctionList --> Calculation1
>            --> FunctionList --> Calculation2
>            --> Calculation3
>
> in the above, if you are listening for changes on Master, then going and
> grabbing values from the Calculations, then who knows what values the
> calculations are going to have!
>
>
> Given your code below (more on that in a second), what you'd want to do is
> create a single ProperyChangeListener and register it with each of your
> calculations, then have the PCL set the label text.  In other words, listen
> to the object(s) who's value(s) you are interested in.
>
>
> So that will work.  Every change to the master list will fire one PC event.
> Then the change will propogate to the first calculation, and it will fire
> another PC event.  Then the change will propogate to the last calculation,
> and you'll get another PC event.
>
> As you can imagine, this is pretty innefficient.  Also, you are maintaining
> a whole set of lists for no other reason than to use them in the
> calculation...
>
> If your data set isn't huge, then this approach will work fine.  But a more
> elegant approach here would be to write your own Calculation object that
> computes just on the master list.  Have it compute the average and sum and
> count (you can just take the code from the sunFloats() and sumIntegers()
> calculations in the GL source), and construct an object that exposes the 3
> totals as properties.
>
> So the calculation will be a Calculation<Summary> instead of 3 calculations.
>
> Then you add a property change listener to the one calculation, and create a
> string from the Summary, then set the label text (on the EDT!).
>
> This may sound daunting, but it's really not.  If you start with the source
> for the calculation that comptuers sumFloats(), you should be able to adapt
> it pretty easily.
>
>
>
> If I were doing this, I'd probably use a binding framework like BBB and
> XProperty to bind the Summary object to the label text, but that's a small
> implementation detail just to make the code cleaner.  For what you are
> doing, a quick and dirty PropertyChangeListener is probably all that's
> needed.
>
> Does that help?
>
> - K
>
> ----------------------- Original Message -----------------------
>
> From: Clayton Carter <[hidden email]>
> To: users <[hidden email]>
> Cc:
> Date: Thu, 25 Feb 2010 23:26:43 -0500
> Subject: FunctionList + Calculations.sumFloats() behaving unpredictably?
>
> I'm really confusing myself with some GL Calculations.  Same old
> story: I have a JTable to display a filtered and sorted list of
> objects.  That part is working fine as far as I can tell.  But I want
> to include a small status message that tells the user how many rows
> are displayed and a handful of other brief stats.  For whatever
> reason, this is being done with a single JLabel whose text is a
> composite of several stats.  (Imagine the Label reading: "Count: 8 /
> Sum: 60 / Average: 7.5" or something.)  For this reason,
> SwingCalculations.bind() doesn't work for me.
>
> Anyway, I create several FunctionLists -  one for each statistic - and
> use an anonymous FunctionList.Function to just select out the
> properties/column values that will be calculated.  I do this as
> follows:
>
> FunctionList intList =
>              new FunctionList<CPSRecord, Integer>( masterListFiltered,
>                                                 new
> FunctionList.Function<CPSRecord, Integer>() {
>                                                    public Integer
> evaluate( CPSRecord p ) {
>                                                       return (
> (CPSSubRecord) p ).getInt();
>                                                    }} );
>
> FunctionList floatList =
>              new FunctionList<CPSRecord, Float>( masterListFiltered,
>                                                  new
> FunctionList.Function<CPSRecord, Float>() {
>                                                     public Float
> evaluate( CPSRecord p ) {
>                                                        return (
> (CPSSubRecord) p ).getFloat();
>                                                     }} );
>
>
> I then generate the Calculations as such:
>
> summaryCount = Calculations.count( masterListFiltered );
> summarySumInt = Calculations.sumIntegers( intList );
> summarySumFloat = Calculations.sumFloats( floatList );
>
>
> I then add "this" as a listener so that I can reset my Label when the
> list(s) are updated.
>
> masterListFiltered.addListEventListener( this );
>
> My listChanged() method simply fires off a call to updateLabel(),
> which more or less just does:
>
> lblStats.setText( buildStatString() );
>
> and buildStatString() is itself very simple:
>
>       String s = "";
>
>       if ( summaryCount != null && summaryCount.getValue() > 0 ) {
>           s += "Count:" + summaryCount.getValue();
>
>           String temp = summarySumInt.getValue().toString();
>           if ( ! temp.equals("") )
>               s += "/SumInt:" + temp;
>
>           t = summarySumFloat.getValue().toString();
>           if ( ! t.equals("") )
>               s += "/SumFloat:" + t;
>       }
>
>       return s;
>
>
> OK, now to explain the unpredictable behavior.  Whenever the list is
> changed (if I change the filter, for example), the statistics are
> updated and the **count and sumInts are always correct**, but the
> sumFloats seem to reflect what the value was just before the list
> changed.
>
> It's hard to find much of a pattern in the results.  Sometimes the
> stats change when I unfocus and refocus the filter text box, but in
> those labels then reflect neither the value from the currently
> displayed list nor from the previously displayed list.
>
> Anything sound familiar, because I fear I'm in over my head.  I'm
> porting a fairly complex app to GlazedLists and have been really
> impressed by what they offer, but I'm often finding myself confused by
> some of their interactions.
>
> Thanks for any help you can offer.
>
> Clayton
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
> --------------------------------------------------------------------- To
> unsubscribe, e-mail: [hidden email] For
> additional commands, e-mail: [hidden email]