- Undocumented Matlab - https://undocumentedmatlab.com -

Setting line position in an edit-box uicontrol

Posted By Yair Altman On March 26, 2009 | 21 Comments

I often see requests in the Matlab forum (CSSM) regarding modifying some uicontrol property that is not exposed by Matlab. Since all Matlab uicontrols are based on underlying Java Swing controls, accessing these features is possible via their Java control peers.
In this post I will give the example of setting the caret (cursor) position in a multi-line edit-box. Apparently, whenever the string contents of such a uicontrol is modified, Matlab automatically sets the caret position on the first character of the first line. It is often requested to place the caret on the last line, so that the last line scrolls into view, rather than the first line. This is the case, for example, if you wish to display an event log that keeps adding new entries at the bottom.
The first step in accessing the underlying Java control is to download my FindJObj submission on the File Exchange [1]. FindJObj searches down the window frame hierarchy until it finds a Java control with the exact position and size of the requested Matlab HG handle (FindJObj has lots of other goodies which will be described in another post).
Once we have the Java peer reference handle (in our case, a UIScrollPane object), we select its internal edit-box control (an object of class com.mathworks.hg.peer.EditTextPeer$hgTextEditMultiline) and use its setCaretPosition() method to move the caret to the end of the text:

>> % Create the multi-line edit-box
>> str = {'multi','line','editbox'};
>> hEdit = uicontrol('style','edit','max',3,'string',str);

Editbox caret at top row (default)
Editbox caret at top row (default)

>> % Get the underlying Java control peer (a scroll-pane object)
>> jhEdit = findjobj(hEdit)
jhEdit =
	javahandle_withcallbacks.com.mathworks.hg.peer.utils.UIScrollPane
>> % Check that the scrollpane has a multiline edit control and 2 scrollbars
>> jhEdit.list
com.mathworks.hg.peer.utils.UIScrollPane[...]
 javax.swing.JViewport[...]
  com.mathworks.hg.peer.EditTextPeer$hgTextEditMultiline[...]
 com.mathworks.hg.peer.utils.UIScrollPane$1[...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[...]
 com.mathworks.hg.peer.utils.UIScrollPane$2[...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[...]
  com.sun.java.swing.plaf.windows.WindowsScrollBarUI$WindowsArrowButton[...]
>> % Get the scroll-pane's internal edit control
>> jEdit = jhEdit.getComponent(0).getComponent(0)
jEdit =
com.mathworks.hg.peer.EditTextPeer$hgTextEditMultiline[...]
>> % Now move the caret position to the end of the text
>> jEdit.setCaretPosition(jEdit.getDocument.getLength);

Editbox caret at bottom (via Java)
Editbox caret at bottom (via Java)

Setting the caret position works, but is actually better done on the EDT using awtinvoke or javaMethodEDT. This will be explained in a separate EDT-specific article [2].

Categories: GUI, Java, Medium risk of breaking in future versions, UI controls


21 Comments (Open | Close)

21 Comments To "Setting line position in an edit-box uicontrol"

#1 Comment By Heiko On April 17, 2009 @ 05:59

Hi. Yesterday I stepped over the findjobj function (actually a very fine piece of work, thank you very much!) while looking for a way to link the selected cells of multiple uitable objects (R2009a). I have four uitables showing related data at different processing stages. What I wanted was to click on one table and select the same cell in all four tables, which is not a native uitable property to set (or even get! The selected cell is given only in the CellSelectionEvent). With findjobj I found several promising methods. The methods “setRowSelectionInterval” and “setColumnSelectionInterval” seemed to link to the method “setSelectionInterval” of the javax.swing.DefaultListSelectionModel but it didn’t work at all. The method “changeSelection” (seems to be a wrapper from the MathWorks) finally did almost what I wanted. It selected the correct cells when I first clicked on a table, but after that, clicking on the tables directly entered the cell editing mode, even if this was disabled for the uitable object, and so the cellSelectionEvent was not fired anymore. I also couldn’t find out what the parameters of the method are. It takes four of them, the first is the row, the second is the column. The other two do change the behavior in an undescribable way. Do you have any hints where I can find out about the parameters of “changeSelection”, and if there is something else I could do to get the behavior I like to have? Maybe I misunderstood the SelectionInterval-functionality, but it didn’t change anything on the java objects. Thank you for reading!

#2 Comment By Yair Altman On April 17, 2009 @ 06:38

You can do 2 things with a standard JTable and the old uitable, but I’m not sure they work with the new uitable (no harm trying):

1. Set all the table columns as non-editable using somthing like the following:

for colIdx = 0 : numCols
tablePeer.setEditable(colIdx,0); % 1:end doesn’t work…
end

2. Set all the table column CellEditors to have infinite ClickCountToStart, like this:

for colIdx = 0 : numCols
try
editor=tablePeer.getColumnModel.getColumn(colIdx).getCellEditor;
editor.setClickCountToStart(intmax); % i.e, never enter edit mode…
catch
% never mind…
end
end

One or both of these may work for you.

#3 Comment By Heiko On April 19, 2009 @ 23:29

Thank you for the answer.

Unfortunately, both of your options don’t work. But while trying I found that fiddling with the java settings alters the uitable properties in an unpredictable way. For instance, the ColumnEditable property is reset to default (1), which caused the described behavior.

Another problem is, that there seems to be a loop through many different callbacks that call my CellSelectionCallback. Especially from the second selection it takes seconds for the tables to react, and the result is wrong.

I stop working on this for now. Thank you again! Bye

#4 Comment By A. Bindemann On June 1, 2009 @ 05:25

Yair,

I’m having a problem with findjobj. It returns an empty result when I pass it the MATLAB handle of an edit box. The problem appears to begin in the call to getRootPanel on line 319 (jRootPane = jFigPanel.getRootPane).

The function falls through to line 346 (jRootPane = jRootPane.getTopLevelAncestor;) which also returns an empty result.

I’m trying to use a MATLAB GUI to display a message log, and would like to position the cursor at the end of the edit box. Interestingly, the edit box behavior under R14SP3 always placed the cursor at the end of the edit box. The behavior changed somewhere between that version and R2007b.

Any ideas you might have would be appreciated.

Thanks,
A. Bindemann

#5 Comment By Yair Altman On June 1, 2009 @ 10:38

@Bindermann – I can think of two reasons for this problem:

1. the figure or one of its components is hidden, thereby causing a problem in retrieving the RootPane and/or TopLevelAncestor (=Frame peer) references.

2. are you using the latest version of FindJObj? – one of the latest versions increased the size/position tolerance used when trying to locate a handle onscreen and this may solve the problem of FindJObj not finding this handle.

If none of these appear to be the cause, then please email me a reproducible code snippet and I’ll try to fix the problem.

#6 Comment By Sylvain On April 18, 2011 @ 22:26

Hi everyone,

I have used the FindObj fonction (great job M. Altman) and the carret does go to the end of the editbox, but the problem is that the view don’t follow the carret…
I would like to know if you have any idea, maybe a simple setting that I don’t know , to get the scrollbar at the bottom of the text (I am quite a beginner with the whole matlab graphic interface).

Regards,

Sylvain

#7 Comment By Yair Altman On April 19, 2011 @ 12:20

This should happen automatically. Perhaps you simply need to add a call to jEdit.repaint();

In any case, here’s how to programmatically move the vertical scrollbar to the bottom:

jVScroll = jhEdit.getVerticalScrollBar;
jVScroll.setValue(jVScroll.getMaximum);
jhEdit.repaint;

More information about the scroll-bars: [9]

#8 Comment By Johannes On September 23, 2011 @ 04:38

Hello Yair,

first of all, thank you for the superb coding, findjobj has saved me from a lot of trouble. I am using your code to set the caret position to the last line inside an edit text box (used as a log inside my GUI) whenever I update the output.
One problem remains: To write something inside the edit text box, I am using

% get existing text
exTex=get(handles.outputWindow,'String');
% new Text to be appended
addTest=sprintf('Some new text');
% write new text 
newText=sprintf('%s \r %s ', exText, addText);
% update output handle
set(handles.outputWindow,'String',newText);

The problem now is: the set command in the last line resets the scroll bar to the top. So if some lines stream into the output window, it jumps to the top and quickly back to the bottom (due to the set.caretPosition). Is there any other way I could write lines into my output window, without resetting the scroll bar to the top?

Thanks and lots of regards from Germany!

#9 Comment By Johannes On September 27, 2011 @ 07:12

Never mind, I found a different solution using listboxes. It works now as I want it to be.

All the best,
Johannes

#10 Comment By Nick On April 18, 2012 @ 06:37

Johannes,

Similar to you, I’m adding a console/log window to a GUI and would like the scroll bar at the bottom. With a list box, were you able to get rid of the ‘jump’ problem altogether?

I think there might be a solution using an edit box by diving deeper into the underlying Java. However, I have only recently started using the findjobj utility, so I could be wrong about that.

Nick

#11 Comment By Sainath M On January 30, 2012 @ 21:13

Hello Yair,

I am facing one problem when I write Java methods in Matlab.
Ex:
>> % Create the multi-line edit-box
>> str = {‘multi’,’line’,’editbox’};
>> hEdit = uicontrol(‘style’,’edit’,’max’,3,’string’,str);

This is the script I am writing in Matlab command window. After that
when I type the code

>> jhEdit = findjobj(hEdit)

Matlab is showing error

??? Undefined function or method ‘findjobj’ for input arguments of type
‘double’.

It is the first time I am using Jmethods in Matlab, will you please guide me what is the problem…

Thank you for your time,

Regards,
Sainath M.

#12 Comment By Yair Altman On January 31, 2012 @ 01:54

@Sainath – read the third paragraph: “The first step in accessing the underlying Java control is to download my FindJObj submission on the File Exchange”

#13 Comment By Sainath M On January 31, 2012 @ 03:40

I can able to work now…
Thank you..

#14 Comment By RK MacLean On November 30, 2012 @ 16:02

Using another one of Yair’s suggestions worked better for me:

 
jhEdit = findjobj(handles.status_text);
jhEdit.anchorToBottom;

#15 Comment By Thomas On August 15, 2013 @ 07:56

Hi Yair,

I have a multi-line editbox with a scrollbar (vertical as needed) and I want it, when activted, to be always on the botton.
I tryed this

 
jVScroll = jScrollPane.getVerticalScrollBar;
jVScroll.setValue(jVScroll.getMaximum);
jScrollPane.repaint; 

and this

 
jhEdit = findjobj(handles.my_editbox);
jhEdit.anchorToBottom; 

but didn’t work… Can you tell me what am I doing wrong?
Thanks

#16 Comment By Yair Altman On August 16, 2013 @ 02:32

@Thomas, perhaps this is done when the control is still not visible, perhaps you’re modifying the control in Matlab later on (this resets the underlying component), perhaps something else. You’ll need to debug it step-by-step to see where the problem is.

#17 Comment By Tiago Silva On January 31, 2014 @ 04:05

Hello Yair,

I’m trying to use something similar to this in order to remember the position of a uitable scrollbar after a data update. My problem is that although I got it work, it only really works in debug mode. The gui I’m developing is fairly complicated, but even a simple example code like the following only works as I’d expect it to do in debug mode:

h = uitable;
set(h,'Data',rand(20));
pause(1);
jh = findjobj(h);
jhScroll = jh.getVerticalScrollBar;
position = 100;
set(h,'Data',rand(20));
jhScroll.setValue(position);

When running this with breakpoints and stepping each line at a time I end up with the uitable updated and the scrollbar at the bottom, as I expected it to behave. Executing the code normally, I can see the uitable is updated but I end up with the scrollbar at the top.

Any idea of what I might be doing wrong? Thanks in advance.

#18 Comment By Yair Altman On January 31, 2014 @ 04:28

@Tiago – I believe that this is another case of [10].

#19 Comment By Tiago On February 3, 2014 @ 03:01

Thanks Yair, the EDT mixup page was helpful. Managed to get my GUI working as I wanted it to.

#20 Comment By Ana GG On October 13, 2015 @ 07:45

Hello,
This seems to work fine for editbox, but how can this be extended to a cell of uitable?
My specific problem is: I have a hint text on a specific editable (text) cell of a table. When I click this cell I want the text to disappear but still I want the cursor to be in the cell to introduce the new value. I have done the first part, but to be able to write on this cell I need to click again, and it would be good if I didn’t have to do it.
Thank you very much in advance,
Ana

#21 Comment By Scott On June 7, 2017 @ 03:16

I’m now using R2017a, and code that used to work with anchorToBottom is no longer working… any ideas?

>> str = {'multi','line','editbox'};
>> hEdit = uicontrol('style','edit','max',3,'string',str);
>> jhEdit = findjobj(hEdit)
jhEdit =
    1×0 empty handle

Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/setting-line-position-in-edit-box-uicontrol

URLs in this post:

[1] FindJObj submission on the File Exchange: http://www.mathworks.com/matlabcentral/fileexchange/14317

[2] EDT-specific article: http://undocumentedmatlab.com/blog/matlab-and-the-event-dispatch-thread-edt/

[3] Additional uicontrol tooltip hacks : https://undocumentedmatlab.com/articles/additional-uicontrol-tooltip-hacks

[4] Uicontrol callbacks : https://undocumentedmatlab.com/articles/uicontrol-callbacks

[5] Setting listbox mouse actions : https://undocumentedmatlab.com/articles/setting-listbox-mouse-actions

[6] Customizing uicontrol border : https://undocumentedmatlab.com/articles/customizing-uicontrol-border

[7] Setting status-bar text : https://undocumentedmatlab.com/articles/setting-status-bar-text

[8] Setting status-bar components : https://undocumentedmatlab.com/articles/setting-status-bar-components

[9] : https://undocumentedmatlab.com/blog/customizing-listbox-editbox-scrollbars/

[10] : https://undocumentedmatlab.com/blog/matlab-and-the-event-dispatch-thread-edt/

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.