Weird UITextArea behaviour working with Strings

Hello, I am reading data from a piece of equipment and dumping it into a UITextarea (orange text)
When I read out the contents of the text area and its class, I get this:
The line pointed to by the arrow isn't relevant. I am after the following numbers to plot (1st 2 columns), i.e. 0 - 836, 1-772 etc
But my plotting routine failed. I think its because the actual data is the 4th entry in the cell array and is just one big string.
Strangely, when I just click in the UITextArea and check the data again, its fine and my plot routing works. It seems the action of clicking has split the long string into individual entries now.
This is my plot routine:
ST=app.MessagesTextArea.Value;
ST=string(ST);
[sy,sx]=size(ST);
data=[];
for i=1:sy
S=ST(i);
TF = contains(S,"focus"); %Ignore the actual calling command
if S=="" || TF==1
continue
end
Sline=split(S)';
n=numel(Sline);
if n>3
S1=Sline(1,1);
S2=Sline(1,2);
data(i,1)=str2double(S1);
data(i,2)=str2double(S2);
end
end
%remove any rows with zeros
data = data(any(data,2),:);
% if data(1,2)==0
% data(1,:)=[];
% end
ax=app.UIAxes3;
cla(ax,'reset');
plot(ax, data(:,1),data(:,2),'.-','Color',cl); grid(ax,"on");
What can i do the avoid having the manually click in the UITextArea to "break my data up" so I can plot it.
(Im not sure if this is relevant, but this is how I get the data initially into the textArea using TCP connection)
data = read(tcpclientObj,nb,"string"); %tcpclientObj this has already been setup
str = formattedDisplayText(data);
ReportMessage(app,str); % this is my own function do display str in the UITextArea
function ReportMessage(app,msg)
currString=get(app.MessagesTextArea,'Value');
%currString=[{char(msg)};currString]; %add to top of message box
currString=[currString; {char(msg)}]; %add to bottom of message box
app.MessagesTextArea.Value=currString;
drawnow;
scroll(app.MessagesTextArea,'bottom');
end
Thanks
Jason

1 Comment

I have found this helps, not sure why though
ST=app.MessagesTextArea.Value;
ST=string(ST);
ST=ST(4);
ST=splitlines(ST);

Sign in to comment.

 Accepted Answer

"It seems the action of clicking has split the long string into individual entries now."
Yes, apparently clicking in a uitextarea causes the Value to be modified such that any character vectors (if it's a cell array of character vectors) or strings (if it's a string array) containing newlines or carriage returns are split at those characters.
This can be a problem, because, as you observed, your code needs to work regardless of whether the Value contains those characters or has been split on those characters.
Maybe the simplest solution is to prevent newline/carriage return characters from getting into the Value at all. Your code is introducing them by using formattedDisplayText. The first thing I would try is getting rid of the use of formattedDisplayText, and just pass the string array returned by read() directly to ReportMessage:
data = read(tcpclientObj,nb,"string");
ReportMessage(app,data);
and modify ReportMessage to handle it:
function ReportMessage(app,msg)
currString=get(app.MessagesTextArea,'Value');
%currString=[cellstr(msg); currString]; %add to top of message box
currString=[currString; cellstr(msg)]; %add to bottom of message box
app.MessagesTextArea.Value=currString;
drawnow;
scroll(app.MessagesTextArea,'bottom');
end
That assumes Value is a cell array of character vectors, which is what you are already using. (I'm running R2022a, whose documentation states that Value can be a string array, but when I try that, the Value I try to set is automatically converted to a cell array of character vectors, even when initializing, as in t=uitextarea("Value",["str1";"str2"]); so I'm sticking with a cell array. If a string array were to work properly as documented, you'd just remove the calls to cellstr above, and you may have to modify how the Value is initialized.)
The point is that if the only newlines/carriage returns in Value were introduced by the use of formattedDisplayText, then the modifications above should fix it.
If that's not the case (i.e., if read() itself is returning strings with newlines/carriage returns in them), then one solution would be to have your code do the splitting, again by modifying ReportMessage so that the Value always has already been split on newlines/carriage returns, but we can burn that bridge when we get to it.

4 Comments

Hi Voss, thamks for your reply. I actually think its the string thats read back (via read()), that has the newlines/carriage returns in them. I think this is why the splitline thing works.
In that case, I would still do:
data = read(tcpclientObj,nb,"string");
ReportMessage(app,data);
and then:
function ReportMessage(app,msg)
% msg is a string array
% splitlines each element of msg
msg = arrayfun(@splitlines,msg,'UniformOutput',false);
% put all together in a string array
msg = vertcat(msg{:});
currString=get(app.MessagesTextArea,'Value');
%currString=[cellstr(msg); currString]; %add to top of message box
currString=[currString; cellstr(msg)]; %add to bottom of message box
app.MessagesTextArea.Value=currString;
drawnow;
scroll(app.MessagesTextArea,'bottom');
end
That is, do the splitting before the new message is appended to the Value, so that clicking or not clicking has no effect, and you don't have to do anything special in the plotting function (each element of Value is a line of text, and don't assume the relevant string is element #4, which may not always be the case).
Perfect, thankyou!

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2022b

Asked:

on 8 Feb 2024

Commented:

on 8 Feb 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!