Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
JTable callbacks

Subject: JTable callbacks

From: Arwel Hughes

Date: 20 Feb, 2008 11:28:04

Message: 1 of 7

Hi,
I have a JTable, which has a callback defined in this way...

table.setModel(tableModel);
set(tableModel,'TableChangedCallback',@myFun);

then, its...

function myFun(src,ev);
..do some stuff...


The table can get modified in the code in two ways - either
the user clicks on the table and manually alters the value
in a cell, or the program can modify the cell contents via
a 'tableModel.setValueAt(val,r,c)' call.

Now, both methods of changing the table call
the 'TableChangedCallback'. However, I need the callback to
do something slightly different depending on whether the
table has been changed by the user or the program. Is there
any way I can distinguish the two in the callback? I've
tried hunting around in src and ev, but havent been able to
find anything obvious.

Cheers,
Arwel

Subject: JTable callbacks

From: Yair Altman

Date: 20 Feb, 2008 19:12:01

Message: 2 of 7

"Arwel Hughes" <a.v.hughes@rl.ac.uk> wrote in message
<fph2s4$mij$1@fred.mathworks.com>...
> Hi,
> I have a JTable, which has a callback defined in this way...
>
> table.setModel(tableModel);
> set(tableModel,'TableChangedCallback',@myFun);
>
> then, its...
>
> function myFun(src,ev);
> ..do some stuff...
>
>
> The table can get modified in the code in two ways - either
> the user clicks on the table and manually alters the value
> in a cell, or the program can modify the cell contents via
> a 'tableModel.setValueAt(val,r,c)' call.
>
> Now, both methods of changing the table call
> the 'TableChangedCallback'. However, I need the callback to
> do something slightly different depending on whether the
> table has been changed by the user or the program. Is there
> any way I can distinguish the two in the callback? I've
> tried hunting around in src and ev, but havent been able to
> find anything obvious.
>
> Cheers,
> Arwel


Hi Arwel,

It should be very easy to update the table's userdata or
appdata (using setappdata) fields just before modifying the
table data programatically, and then checking this value
within your callback and clearing it. When the callback is
called following manual user entry, the value remains
cleared and you'll know that the user modified the data, not
the program.

Yair Altman
http://ymasoftware.com

Subject: JTable callbacks

From: Arwel Hughes

Date: 21 Feb, 2008 09:36:02

Message: 3 of 7

Hi Yair,
Aha! Good plan!
Many thanks as ususal Yair.
Arwel





"Yair Altman" <altmanyDEL@gmailDEL.comDEL> wrote in message
<fphu21$aef$1@fred.mathworks.com>...
> "Arwel Hughes" <a.v.hughes@rl.ac.uk> wrote in message
> <fph2s4$mij$1@fred.mathworks.com>...
> > Hi,
> > I have a JTable, which has a callback defined in this
way...
> >
> > table.setModel(tableModel);
> > set(tableModel,'TableChangedCallback',@myFun);
> >
> > then, its...
> >
> > function myFun(src,ev);
> > ..do some stuff...
> >
> >
> > The table can get modified in the code in two ways -
either
> > the user clicks on the table and manually alters the
value
> > in a cell, or the program can modify the cell contents
via
> > a 'tableModel.setValueAt(val,r,c)' call.
> >
> > Now, both methods of changing the table call
> > the 'TableChangedCallback'. However, I need the
callback to
> > do something slightly different depending on whether
the
> > table has been changed by the user or the program. Is
there
> > any way I can distinguish the two in the callback? I've
> > tried hunting around in src and ev, but havent been
able to
> > find anything obvious.
> >
> > Cheers,
> > Arwel
>
>
> Hi Arwel,
>
> It should be very easy to update the table's userdata or
> appdata (using setappdata) fields just before modifying
the
> table data programatically, and then checking this value
> within your callback and clearing it. When the callback is
> called following manual user entry, the value remains
> cleared and you'll know that the user modified the data,
not
> the program.
>
> Yair Altman
> http://ymasoftware.com
>

Subject: JTable callbacks

From: Yair Altman

Date: 21 Sep, 2008 23:22:01

Message: 4 of 7

Mikhail <razum@gmx.com> wrote in message <17460783.1219566963294.JavaMail.jakarta@nitrogen.mathforum.org>...
> The approach of Yair works fine unless the value is being changed continously. Scenario: you are moving mouse and continously performing some calculations with the result being displayed in the JTable. Then the burden of continously calling TableChangedCallback is too high. The same applies for the manual vs. programmatic cell selection. The problem is aggravated by the fact that if callbacks are being fired too frequently then they are being interupted and checking programmatic/manual does not happen at all.
>
> My solution it to prevent callback from being fired at all. Write your own setValueAt() method in java which removes matlab listener from the java component, do waht you want with JTable and then add listener back. Methods used are: getTableModelListeners, removeTableModelListeners and addTableModelListeners. The listener name is "class javax.swing.event.TableModelListenerLIAdapterClass".
>
> This java-side operation is very fast and solves the problem definitively.


Hi Mikhail,

I'm not exactly sure to which of my approaches you referred (assuming I'm the Yair you mentioned...), since this thread does not cite any previous posting. However, the problem you've detailed is indeed correct and happens whenever a Matlab callback is assigned to any rapidly-changing Java object (JTable, JSlider and relatives). At some point, depending on the user's specific system, the callback event queue is overloaded and events are simply discarded. This is a good source of frustration, since the problem never happens during debugging...

The simple solution is to temporarily disable the object during callback, preventing user-generated data updates; another Matlab-based approach is to temporarily disable the callback before modifying the data (set(obj,'_Callback',[]) or obj._Callback=[];), restoring it after the modification [also in the catch block - remember that any update can crash so you must enclose it in a try-catch block]. Both of these solutions do not require any Java knowledge.

A better yet more complex solution (requiring Java knowledge) is using your approach, of temporary listener disabling. Another related approach, also requiring Java knowledge, is to set the callback in Java rather than in Matlab. I'm afraid that most Matlab programmers do not have enough Java experience for either of these approach and would therefore need to rely on one of the Matlab-based approaches.

Yair Altman

Subject: JTable callbacks

From: Steven Lord

Date: 22 Sep, 2008 13:40:46

Message: 5 of 7


"Yair Altman" <altmanyDEL@gmailDEL.comDEL> wrote in message
news:gb6kup$c24$1@fred.mathworks.com...
> Mikhail <razum@gmx.com> wrote in message
> <17460783.1219566963294.JavaMail.jakarta@nitrogen.mathforum.org>...
>> The approach of Yair works fine unless the value is being changed
>> continously. Scenario: you are moving mouse and continously performing
>> some calculations with the result being displayed in the JTable. Then the
>> burden of continously calling TableChangedCallback is too high. The same
>> applies for the manual vs. programmatic cell selection. The problem is
>> aggravated by the fact that if callbacks are being fired too frequently
>> then they are being interupted and checking programmatic/manual does not
>> happen at all.
>>
>> My solution it to prevent callback from being fired at all. Write your
>> own setValueAt() method in java which removes matlab listener from the
>> java component, do waht you want with JTable and then add listener back.
>> Methods used are: getTableModelListeners, removeTableModelListeners and
>> addTableModelListeners. The listener name is "class
>> javax.swing.event.TableModelListenerLIAdapterClass".
>>
>> This java-side operation is very fast and solves the problem
>> definitively.
>
>
> Hi Mikhail,
>
> I'm not exactly sure to which of my approaches you referred (assuming I'm
> the Yair you mentioned...), since this thread does not cite any previous
> posting. However, the problem you've detailed is indeed correct and
> happens whenever a Matlab callback is assigned to any rapidly-changing
> Java object (JTable, JSlider and relatives). At some point, depending on
> the user's specific system, the callback event queue is overloaded and
> events are simply discarded. This is a good source of frustration, since
> the problem never happens during debugging...
>
> The simple solution is to temporarily disable the object during callback,
> preventing user-generated data updates; another Matlab-based approach is
> to temporarily disable the callback before modifying the data
> (set(obj,'_Callback',[]) or obj._Callback=[];), restoring it after the
> modification [also in the catch block - remember that any update can crash
> so you must enclose it in a try-catch block]. Both of these solutions do
> not require any Java knowledge.

If you're using Release R2008a or later, you can use an onCleanup object to
restore the existing callback. When the variable containing the onCleanup
object goes out of scope (most often because the function exits or you
explicitly clear the variable) the onCleanup object's "callback" executes.

http://www.mathworks.com/access/helpdesk/help/techdoc/ref/oncleanup.html

--
Steve Lord
slord@mathworks.com

Subject: JTable callbacks

From: Mikhail

Date: 1 Oct, 2008 22:29:17

Message: 6 of 7

Hello Yair,

with R2006a I had buggy behaviour with this approach (entirely in matlab)

set(obj,'xxxCallback',[])
updateXXX();
set(obj,'xxxCallback',@xxxFcn)

The third line was executed but callback was not set to xxxFcn but remained []. So I had to do it in Java, it was OK because it was anyway a heavily customized JTable.

Subject: JTable callbacks

From: Yair Altman

Date: 1 Oct, 2008 23:15:08

Message: 7 of 7

Mikhail <razum@gmx.com> wrote in message <17161457.1222900188516.JavaMail.jakarta@nitrogen.mathforum.org>...
> Hello Yair,
>
> with R2006a I had buggy behaviour with this approach (entirely in matlab)
>
> set(obj,'xxxCallback',[])
> updateXXX();
> set(obj,'xxxCallback',@xxxFcn)
>
> The third line was executed but callback was not set to xxxFcn but remained []. So I had to do it in Java, it was OK because it was anyway a heavily customized JTable.

Hi Mikhail,
I think this issue might be a typical example of Java synchronicity problems due to Matlab's use of the EventDispatchThread. My hunch is that in this case, updateXXX() has still not completed before the Matlab engine executed the set(obj,'xxxCallback',...) call, which therefore silently failed. Your solution of restoring the callback in Java worked because it restored thread synchronicity.

The "correct/official" way to do this in Matlab would be to use EDT-safe methods (awtinvoke etc.). But, since these are so problematic and cumbersome, in most cases a simple pause(0.01) call before the set() will solve the problem. play around with different pause values to find what works for your particular app/OS/HW. It's ugly but works well...

Yair Altman

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us