2

I have a simple POJO like so:

class A{
    private int a;
    private int b;

    public int getC(){
        return a + b;
    }

    //getters and setters for a and b
}

This entity is bound using BindingBeans to a JTable. Any changes made to a and b are properly handled and displayed in the JTable, however, c does not update.

I think I need to fire a property change event or something if a or b is updated, but really have no ideas. Any ideas?

EDIT:

I have created a simple example:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.Serializable;


public class POJO implements Serializable{

    private static final Gson gson = new GsonBuilder().create();

    private Integer a;
    private Integer b;

    public Integer getC() {
        return a + b;
    }

    public Integer getA() {
        return a;
    }

    public void setA(Integer a) {
        this.a = a;
    }

    public Integer getB() {
        return b;
    }

    public void setB(Integer b) {
        this.b = b;
    }

    @Override
    public String toString(){
        return gson.toJson(this);
    }
}

And the Main class

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import org.jdesktop.beansbinding.AutoBinding;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.swingbinding.JTableBinding;
import org.jdesktop.swingbinding.SwingBindings;


public class Example implements ActionListener{

    private JTable table;
    private JFrame frame;
    private JTableBinding tableBinding;
    private List<POJO> elements;

    public static void main(String [] args){
        new Example();
    }

    public Example(){
        initData();
        initGui();
        initBindings();
        frame.pack();
    }

    private void initData(){
        elements = new ArrayList<POJO>();
        POJO pojoA = new POJO();
        pojoA.setA(1);
        pojoA.setB(2);
        POJO pojoB = new POJO();
        pojoB.setA(3);
        pojoB.setB(4);
        elements.add(pojoA);
        elements.add(pojoB);
    }

    private void initGui(){
         frame = new JFrame();
         table = new JTable();
         frame.getContentPane().setLayout(new BorderLayout());
         JPanel tablePanel = new JPanel();
         tablePanel.setLayout(new GridLayout());
         tablePanel.add(table);
         frame.getContentPane().add(BorderLayout.CENTER,tablePanel);
         JButton button = new JButton("Show Current Elements");
         button.addActionListener(this);
         frame.getContentPane().add(BorderLayout.SOUTH,button);
         frame.setLocationRelativeTo(null);
         frame.setVisible(true);
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void initBindings(){
        tableBinding = SwingBindings.createJTableBinding(
                AutoBinding.UpdateStrategy.READ_WRITE, elements,
                table);
        addBinding("a", "A", Integer.class, true);
        addBinding("b", "B", Integer.class, true);
        addBinding("c", "C", Integer.class, false);
        tableBinding.bind();
    }

    private void addBinding(String properyName, String columnName, Class clazz, boolean editable) {
        BeanProperty beanProperty = BeanProperty.create(properyName);
        JTableBinding.ColumnBinding columnBinding = tableBinding.addColumnBinding(beanProperty);
        columnBinding.setColumnName(columnName);
        columnBinding.setColumnClass(clazz);
        columnBinding.setEditable(editable);
    }

    public void actionPerformed(ActionEvent ae) {
        StringBuilder builder = new StringBuilder();
        for(POJO pojo : elements){
            builder.append(pojo.toString() + "\n");
        }
        JOptionPane.showMessageDialog(null, "The elements are:\n\n" + builder.toString());
    }
}
divibisan
  • 11,659
  • 11
  • 40
  • 58
user489041
  • 27,916
  • 55
  • 135
  • 204
  • Shouldn't you have a setC method that adds a and b instead of doing in getC? I don't see any property called c in your class nor a setter for the same. – Chetan Kinger Mar 05 '15 at 15:47
  • Agreed, but in the context of my app, setting C doesnt make sense. C is simply the combination of a and b. When a or b is updating, I want the changes to C to be reflected in the table. They are not currently. – user489041 Mar 05 '15 at 15:51
  • Maybe use a CellEditorListener? – Chetan Kinger Mar 05 '15 at 15:56
  • How would the binding be notified if you change `a` or `b`. Aren't you supposed to make those private, create getters and setters for it and fire property changes (e.g. using PropertyChangeSupport) – Robin Mar 05 '15 at 16:02
  • @Robin Please see my edit for how I create my bindings – user489041 Mar 05 '15 at 16:03
  • 1. not joke :-) have to read :-) Oracle tutorial - How to use Table, parts about model, renderer and editor (custom too), 2. don't to mix events from view and model, 3. then after post an SSCCE/MCVE, short, runnable, compilable with hardcode value for POJO from/in simple loop – mKorbel Mar 05 '15 at 16:30
  • standard JTableBinding from some outdated JSR295/296 is road to the hell, better is to buy JIDE (why bothering with), or SwingX has one-two attemtp-s AFAIK – mKorbel Mar 05 '15 at 16:33
  • @user489041 Again, you just have public fields, not beans. I have no experience with your bindings-framework but I doubt it will work with a non-bean – Robin Mar 05 '15 at 16:44
  • @Robin The modifier access my point in that example. I have changed them to private. – user489041 Mar 05 '15 at 16:46
  • @mKorbel I have created a runnable example. Not when you click the button, it does show that the table is bound to the list of elements, but C does not update in the table. My original question is, I just need C to update in the table when A or B has changed. I wanted to know if this was possible using my framework. – user489041 Mar 05 '15 at 17:00
  • @user489041 forgot for JSR (btw I'm sure that Netbeans has two-three tutorials about), I'd be put together Robins answer here and custom Beans + [PropertyChangeSupport by kleopatra](http://stackoverflow.com/questions/17930500/java-beansbinding-jbutton-enabled/17942625#17942625) (AbstractBeant ala POJO reduces everything that came from JSRXxx) – mKorbel Mar 05 '15 at 18:51
  • @user489041 important is to see what paramaters are used/set in her CustomBean, by default now is very good question with good answer, plus one – mKorbel Mar 05 '15 at 18:53

1 Answers1

2

In order to have a correct bean, you need to fire events

private final PropertyChangeSupport = new PropertyChangeSupport( this );

public void setA(Integer a) {
  Integer old = this.a;
  this.a = a;
  propertyChangeSupport.firePropertyChange( "A", old, this.a );
}

C is a derived property. Not sure whether it will work if you only have a getter and no setter. But you most likely need to fire an event in case C changes as well. Since it changes when A or B change, I would update their setters to

public void setA(Integer a) {
  Integer oldA = this.a;
  Integer oldC = getC();
  this.a = a;
  propertyChangeSupport.firePropertyChange( "A", oldA, this.a );
  propertyChangeSupport.firePropertyChange( "C", oldC, getC() );
}

The same applies of course to the B property.

But as commented earlier, I have no experience with that binding framework. So not sure whether this will solve your issue and I haven't tested it (not planning on downloading/installing that framework first).

Robin
  • 36,233
  • 5
  • 47
  • 99